diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000..f985ec4de5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,252 @@ + + 4.0.0 + alfresco-data-model + Alfresco Data model classes + + alfresco-parent + org.alfresco + 5.2.1-SNAPSHOT + ../../pom.xml + + + + + + 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 + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.jibx + + maven-jibx-plugin + + + [1.2.5,) + + + bind + + + + + true + true + + + + + + + + + + + + + + org.alfresco + alfresco-core + + + + javax.servlet + servlet-api + provided + + + + jaxen + jaxen + + + org.jibx + jibx-run + ${dependency.jibx.version} + + + + org.antlr + antlr + ${dependency.antlr.version} + + + org.apache.chemistry.opencmis + chemistry-opencmis-client-impl + ${dependency.opencmis.version} + + + junit + junit + + + org.jvnet.staxex + stax-ex + + + + + org.apache.chemistry.opencmis + chemistry-opencmis-commons-impl + ${dependency.opencmis.version} + + + com.sun.xml.messaging.saaj + saaj-impl + + + org.jvnet.staxex + stax-ex + + + + + + + org.jvnet.staxex + stax-ex + 1.2 + + + org.apache.chemistry.opencmis + chemistry-opencmis-server-bindings + ${dependency.opencmis.version} + + + org.jvnet.staxex + stax-ex + + + + + org.codehaus.woodstox + woodstox-core-asl + 4.2.0 + + + + org.acegisecurity + acegi-security + 0.8.2_patched + + + org.alfresco + alfresco-xmlfactory + + + xpp3 + xpp3 + 1.1.3_8 + + + + org.apache.tika + tika-core + ${dependency.tika.version} + + + org.apache.tika + tika-parsers + ${dependency.tika.version} + + + org.gagravarr + vorbis-java-core + ${dependency.vorbisJava.version} + + + org.gagravarr + vorbis-java-tika + ${dependency.vorbisJava.version} + + + com.googlecode.juniversalchardet + juniversalchardet + 1.0.3 + + + + + junit + junit + test + + + org.antlr + gunit + ${dependency.antlr.version} + test + + + org.mockito + mockito-all + test + + + diff --git a/src/main/java/org/alfresco/encoding/TikaCharsetFinder.java b/src/main/java/org/alfresco/encoding/TikaCharsetFinder.java new file mode 100644 index 0000000000..2c7b98c860 --- /dev/null +++ b/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/src/main/java/org/alfresco/model/ContentModel.java b/src/main/java/org/alfresco/model/ContentModel.java new file mode 100644 index 0000000000..bfac3dc83b --- /dev/null +++ b/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/src/main/java/org/alfresco/model/RenditionModel.java b/src/main/java/org/alfresco/model/RenditionModel.java new file mode 100644 index 0000000000..c7d41d7cba --- /dev/null +++ b/src/main/java/org/alfresco/model/RenditionModel.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.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 +{ + static final QName ASPECT_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition"); + static final QName ASPECT_HIDDEN_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "hiddenRendition"); + 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/src/main/java/org/alfresco/opencmis/CMISAccessControlFormatEnum.java b/src/main/java/org/alfresco/opencmis/CMISAccessControlFormatEnum.java new file mode 100644 index 0000000000..e4244ae71d --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/CMISUtils.java b/src/main/java/org/alfresco/opencmis/CMISUtils.java new file mode 100644 index 0000000000..29f5a5d696 --- /dev/null +++ b/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(); + out.close(); + + 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/src/main/java/org/alfresco/opencmis/EnumFactory.java b/src/main/java/org/alfresco/opencmis/EnumFactory.java new file mode 100644 index 0000000000..7fe60b4930 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/EnumLabel.java b/src/main/java/org/alfresco/opencmis/EnumLabel.java new file mode 100644 index 0000000000..edb1454fde --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/AbstractTypeDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/AbstractTypeDefinitionWrapper.java new file mode 100644 index 0000000000..69131de33b --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/BasePropertyDefintionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/BasePropertyDefintionWrapper.java new file mode 100644 index 0000000000..b96b166c4c --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryService.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryService.java new file mode 100644 index 0000000000..a7c12510b7 --- /dev/null +++ b/src/main/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryService.java @@ -0,0 +1,507 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 singletonCache; // eg. for openCmisDictionaryRegistry + 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.singletonCache = 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; + boolean readLockReleased = false; + //Make sure that DictionaryRegistry exist + dictionaryDAO.getDictionaryRegistry(tenant); + + registryReadLock.lock(); + try + { + String cacheKey = getCacheKey(tenant); + cmisRegistry = singletonCache.get(cacheKey); + if(cmisRegistry == null) + { + registryReadLock.unlock(); + readLockReleased = true; + + registryWriteLock.lock(); + try + { + cmisRegistry = singletonCache.get(cacheKey); + if(cmisRegistry == null) + { + cmisRegistry = createDictionaryRegistry(tenant); + } + } + finally + { + registryWriteLock.unlock(); + } + } + } + finally + { + if(!readLockReleased) + { + registryReadLock.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() + { + CMISDictionaryRegistry cmisRegistry = null; + + String tenant = TenantUtil.getCurrentDomain(); + + registryWriteLock.lock(); + try + { + cmisRegistry = createDictionaryRegistry(tenant); + } + finally + { + registryWriteLock.unlock(); + } + + return cmisRegistry; + } + + protected CMISDictionaryRegistry createDictionaryRegistry(String tenant) + { + CMISDictionaryRegistry cmisRegistry = null; + String cacheKey = getCacheKey(tenant); + + if(tenant.equals(TenantService.DEFAULT_DOMAIN)) + { + cmisRegistry = createCoreDictionaryRegistry(); + } + else + { + cmisRegistry = createTenantDictionaryRegistry(tenant); + } + + // publish new registry + singletonCache.put(cacheKey, cmisRegistry); + + 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(); + singletonCache.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/src/main/java/org/alfresco/opencmis/dictionary/CMISActionEvaluator.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISActionEvaluator.java new file mode 100644 index 0000000000..3936234e20 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistry.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistry.java new file mode 100644 index 0000000000..eb3e98c1d1 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistryImpl.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistryImpl.java new file mode 100644 index 0000000000..3db14e8c31 --- /dev/null +++ b/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistryImpl.java @@ -0,0 +1,538 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.error.AlfrescoRuntimeException; +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/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryReload.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryReload.java new file mode 100644 index 0000000000..cdaa202552 --- /dev/null +++ b/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryReload.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.opencmis.dictionary; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +/** + * Temporary workaround for: + *

+ * + * TODO: Remove this bean when rework for MNT-14819 is complete. + * + * @author Matt Ward + */ +public final class CMISDictionaryReload extends AbstractLifecycleBean +{ + private static final Log log = LogFactory.getLog(CMISDictionaryReload.class); + private final CMISAbstractDictionaryService cmisDictService; + private final boolean enabled; + + public CMISDictionaryReload(CMISAbstractDictionaryService cmisDictService, boolean enabled) + { + this.cmisDictService = cmisDictService; + this.enabled = enabled; + } + + public void reload() + { + if (enabled) + { + // Avoid deadlock by making sure we already have a registry present. + cmisDictService.getRegistry(); + log.debug("Reloading CMIS dictionary."); + cmisDictService.afterDictionaryInit(); + } + } + + @Override + protected void onBootstrap(ApplicationEvent event) + { + reload(); + } + + @Override + protected void onShutdown(ApplicationEvent event) + { + // Do nothing. + } +} diff --git a/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryService.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryService.java new file mode 100644 index 0000000000..ecdf9abe60 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISNodeInfo.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISNodeInfo.java new file mode 100644 index 0000000000..29f2faaad7 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISObjectVariant.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISObjectVariant.java new file mode 100644 index 0000000000..cb0442f3bb --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyAccessor.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyAccessor.java new file mode 100644 index 0000000000..c408577ebd --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyLuceneBuilder.java new file mode 100644 index 0000000000..063af0462d --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/CMISStrictDictionaryService.java b/src/main/java/org/alfresco/opencmis/dictionary/CMISStrictDictionaryService.java new file mode 100644 index 0000000000..610f8a8f5d --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/DocumentTypeDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/DocumentTypeDefinitionWrapper.java new file mode 100644 index 0000000000..0b334e3591 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/FilteredDictionaryComponent.java b/src/main/java/org/alfresco/opencmis/dictionary/FilteredDictionaryComponent.java new file mode 100644 index 0000000000..42240855e2 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/FolderTypeDefintionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/FolderTypeDefintionWrapper.java new file mode 100644 index 0000000000..4b3dc9e6e6 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/ItemTypeDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/ItemTypeDefinitionWrapper.java new file mode 100644 index 0000000000..ffa77fca81 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/PolicyTypeDefintionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/PolicyTypeDefintionWrapper.java new file mode 100644 index 0000000000..a524302f25 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/PropertyAccessorMapping.java b/src/main/java/org/alfresco/opencmis/dictionary/PropertyAccessorMapping.java new file mode 100644 index 0000000000..2b44d698f3 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/PropertyDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/PropertyDefinitionWrapper.java new file mode 100644 index 0000000000..898dfaafdf --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/PropertyLuceneBuilderMapping.java b/src/main/java/org/alfresco/opencmis/dictionary/PropertyLuceneBuilderMapping.java new file mode 100644 index 0000000000..44307c106c --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/QNameFilter.java b/src/main/java/org/alfresco/opencmis/dictionary/QNameFilter.java new file mode 100644 index 0000000000..380a12ecff --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/QNameFilterImpl.java b/src/main/java/org/alfresco/opencmis/dictionary/QNameFilterImpl.java new file mode 100644 index 0000000000..965f7f9a67 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/RelationshipTypeDefintionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/RelationshipTypeDefintionWrapper.java new file mode 100644 index 0000000000..affd9ff925 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/SecondaryTypeDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/SecondaryTypeDefinitionWrapper.java new file mode 100644 index 0000000000..8213d9a06f --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/ShadowTypeDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/ShadowTypeDefinitionWrapper.java new file mode 100644 index 0000000000..29e628418c --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/dictionary/TypeDefinitionWrapper.java b/src/main/java/org/alfresco/opencmis/dictionary/TypeDefinitionWrapper.java new file mode 100644 index 0000000000..59a2f1ea28 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/AbstractSimpleLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/AbstractSimpleLuceneBuilder.java new file mode 100644 index 0000000000..91b1f34d8b --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/BaseLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/BaseLuceneBuilder.java new file mode 100644 index 0000000000..ddb8e15a31 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/BaseTypeIdLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/BaseTypeIdLuceneBuilder.java new file mode 100644 index 0000000000..14e100e2d4 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/CMISMapping.java b/src/main/java/org/alfresco/opencmis/mapping/CMISMapping.java new file mode 100644 index 0000000000..951d2b1bdc --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/ContentStreamLengthLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/ContentStreamLengthLuceneBuilder.java new file mode 100644 index 0000000000..3b8e58e70e --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/ContentStreamMimetypeLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/ContentStreamMimetypeLuceneBuilder.java new file mode 100644 index 0000000000..89faca9ee1 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/DirectLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/DirectLuceneBuilder.java new file mode 100644 index 0000000000..37c24370ae --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/FixedValueLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/FixedValueLuceneBuilder.java new file mode 100644 index 0000000000..09c3979787 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/NotSupportedLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/NotSupportedLuceneBuilder.java new file mode 100644 index 0000000000..323f551c39 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/ObjectIdLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/ObjectIdLuceneBuilder.java new file mode 100644 index 0000000000..487fd1943a --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/ObjectTypeIdLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/ObjectTypeIdLuceneBuilder.java new file mode 100644 index 0000000000..41696c23ee --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/ParentLuceneBuilder.java b/src/main/java/org/alfresco/opencmis/mapping/ParentLuceneBuilder.java new file mode 100644 index 0000000000..31184f229b --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/mapping/RuntimePropertyLuceneBuilderMapping.java b/src/main/java/org/alfresco/opencmis/mapping/RuntimePropertyLuceneBuilderMapping.java new file mode 100644 index 0000000000..c9d610aeab --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/search/CMISFTSQueryParser.java b/src/main/java/org/alfresco/opencmis/search/CMISFTSQueryParser.java new file mode 100644 index 0000000000..9751abe710 --- /dev/null +++ b/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/src/main/java/org/alfresco/opencmis/search/CMISQueryOptions.java b/src/main/java/org/alfresco/opencmis/search/CMISQueryOptions.java new file mode 100644 index 0000000000..9556647ee0 --- /dev/null +++ b/src/main/java/org/alfresco/opencmis/search/CMISQueryOptions.java @@ -0,0 +1,193 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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()); + 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()); + return searchParameters; + } +} diff --git a/src/main/java/org/alfresco/opencmis/search/CMISQueryParser.java b/src/main/java/org/alfresco/opencmis/search/CMISQueryParser.java new file mode 100644 index 0000000000..1b219c8c4d --- /dev/null +++ b/src/main/java/org/alfresco/opencmis/search/CMISQueryParser.java @@ -0,0 +1,1718 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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); + 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, null, 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) + { + 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); + + } + 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()); + } + } + return factory.createSelector(typeDef.getAlfrescoClass(), alias); + } 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); + + List list = (List) (source.getChildren()); + for (CommonTree joinNode : list) + { + if (joinNode.getType() == CMISParser.JOIN) + { + CommonTree rhsSource = (CommonTree) joinNode.getFirstChildWithType(CMISParser.SOURCE); + Source rhs = buildSource(rhsSource, joinSupport, factory); + + JoinType joinType = JoinType.INNER; + CommonTree joinTypeNode = (CommonTree) joinNode.getFirstChildWithType(CMISParser.LEFT); + if (joinTypeNode != null) + { + joinType = JoinType.LEFT; + } + + if ((joinType == JoinType.LEFT) && (joinSupport == CapabilityJoin.INNERONLY)) + { + throw new UnsupportedOperationException("Outer joins are not supported"); + } + + 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/src/main/java/org/alfresco/opencmis/search/CmisFunctionEvaluationContext.java b/src/main/java/org/alfresco/opencmis/search/CmisFunctionEvaluationContext.java new file mode 100644 index 0000000000..df6d9ed887 --- /dev/null +++ b/src/main/java/org/alfresco/opencmis/search/CmisFunctionEvaluationContext.java @@ -0,0 +1,552 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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_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/src/main/java/org/alfresco/repo/cache/LockingCache.java b/src/main/java/org/alfresco/repo/cache/LockingCache.java new file mode 100644 index 0000000000..316d265762 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/cache/MemoryCache.java b/src/main/java/org/alfresco/repo/cache/MemoryCache.java new file mode 100644 index 0000000000..882760b322 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/cache/SimpleCache.java b/src/main/java/org/alfresco/repo/cache/SimpleCache.java new file mode 100644 index 0000000000..eb49ea713d --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/content/ContentContext.java b/src/main/java/org/alfresco/repo/content/ContentContext.java new file mode 100644 index 0000000000..7ff9bf3ab3 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/content/ContentStore.java b/src/main/java/org/alfresco/repo/content/ContentStore.java new file mode 100644 index 0000000000..8109e72bf6 --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/ContentStore.java @@ -0,0 +1,284 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.util.Date; + +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. For example, the 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); + + /** + * Get all URLs for the store, regardless of creation time. + * @throws ContentIOException + * if an IO error occurs + * @throws UnsupportedOperationException + * if the store is unable to provide the information + * + * @see #getUrls(Date, Date, ContentUrlHandler) + * + * @deprecated in 5.0. The API is no longer used by Alfresco; + * efficient APIs can be provided by the implementations, if required + */ + @Deprecated + public void getUrls(ContentUrlHandler handler) throws ContentIOException; + + /** + * Get a set of all content URLs in the store. This indicates all content available for reads. + * + * @param createdAfter + * all URLs returned must have been created after this date. May be null. + * @param createdBefore + * all URLs returned must have been created before this date. May be null. + * @param handler + * the callback that will passed each URL + * @throws ContentIOException + * if an error occurs + * @throws UnsupportedOperationException + * if the store is unable to provide the information + * + * @deprecated in 5.0. The API is no longer used by Alfresco; + * efficient APIs can be provided by the implementations, if required + */ + @Deprecated + public void getUrls(Date createdAfter, Date createdBefore, ContentUrlHandler handler) throws ContentIOException; + + /** + * 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); + + /** + * Iterface for to use during iteration over content URLs. + * + * @author Derek Hulley + * @since 2.0 + * @deprecated in 5.0 + */ + @Deprecated + public interface ContentUrlHandler + { + void handle(String contentUrl); + } +} diff --git a/src/main/java/org/alfresco/repo/content/ContentStoreCaps.java b/src/main/java/org/alfresco/repo/content/ContentStoreCaps.java new file mode 100644 index 0000000000..44bdd26744 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/content/MimetypeMap.java b/src/main/java/org/alfresco/repo/content/MimetypeMap.java new file mode 100644 index 0000000000..3d638599ca --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/MimetypeMap.java @@ -0,0 +1,935 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.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; + +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; + +/** + * 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); + 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; + } + + /** + * 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/src/main/java/org/alfresco/repo/content/encoding/ContentCharsetFinder.java b/src/main/java/org/alfresco/repo/content/encoding/ContentCharsetFinder.java new file mode 100644 index 0000000000..b02b755307 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/AbstractDictionaryRegistry.java b/src/main/java/org/alfresco/repo/dictionary/AbstractDictionaryRegistry.java new file mode 100644 index 0000000000..74625eb3d2 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/CompiledModel.java b/src/main/java/org/alfresco/repo/dictionary/CompiledModel.java new file mode 100644 index 0000000000..9de963a59b --- /dev/null +++ b/src/main/java/org/alfresco/repo/dictionary/CompiledModel.java @@ -0,0 +1,459 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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) + { + 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/src/main/java/org/alfresco/repo/dictionary/CompiledModelsCache.java b/src/main/java/org/alfresco/repo/dictionary/CompiledModelsCache.java new file mode 100644 index 0000000000..a193cbd0f9 --- /dev/null +++ b/src/main/java/org/alfresco/repo/dictionary/CompiledModelsCache.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.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.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; + } +} diff --git a/src/main/java/org/alfresco/repo/dictionary/CoreDictionaryRegistryImpl.java b/src/main/java/org/alfresco/repo/dictionary/CoreDictionaryRegistryImpl.java new file mode 100644 index 0000000000..b0e88c45e7 --- /dev/null +++ b/src/main/java/org/alfresco/repo/dictionary/CoreDictionaryRegistryImpl.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.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(); + } + + // notify registered listeners that dictionary has been initialised (population is complete) + for (DictionaryListener dictionaryListener : dictionaryDAO.getDictionaryListeners()) + { + dictionaryListener.afterDictionaryInit(); + } + + // 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 + +// if(compiledModels.get(model.getModelDefinition().getName()) != null) +// { +// throw new AlfrescoRuntimeException("Cannot override existing model " + model.getModelDefinition().getName()); +// } +// +// for(M2Namespace namespace : model.getM2Model().getNamespaces()) +// { +// if(uriToModels.get(namespace.getUri()) != null) +// { +// throw new AlfrescoRuntimeException("Cannot override existing namespace " + namespace.getUri()); +// } +// } + + QName qname = super.putModelImpl(model); + +// if(dictionaryDAO.isContextRefreshed()) +// { +// for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners()) +// { +// if(listener instanceof ExtendedDictionaryListener) +// { +// ((ExtendedDictionaryListener)listener).coreModelAdded(model); +// } +// } +// } + + return qname; + } + + @Override + public void removeImpl() + { + for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners()) + { + listener.afterDictionaryDestroy(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/alfresco/repo/dictionary/CustomModelDefinitionImpl.java b/src/main/java/org/alfresco/repo/dictionary/CustomModelDefinitionImpl.java new file mode 100644 index 0000000000..7b86ed3356 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/CustomModelsInfo.java b/src/main/java/org/alfresco/repo/dictionary/CustomModelsInfo.java new file mode 100644 index 0000000000..63ecd594b8 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DelegateModelQuery.java b/src/main/java/org/alfresco/repo/dictionary/DelegateModelQuery.java new file mode 100644 index 0000000000..3f1fd273a6 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DictionaryBootstrap.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryBootstrap.java new file mode 100644 index 0000000000..256eefbb2e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DictionaryComponent.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryComponent.java new file mode 100644 index 0000000000..3f1e3dca86 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DictionaryDAO.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryDAO.java new file mode 100644 index 0000000000..34cb5d7fae --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java new file mode 100644 index 0000000000..200eb6b4a5 --- /dev/null +++ b/src/main/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java @@ -0,0 +1,1054 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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); + getThreadLocal().put("", dictionaryRegistry); + dictionaryRegistry.init(); + getThreadLocal().remove(""); + return dictionaryRegistry; + } + + private DictionaryRegistry createTenantDictionaryRegistry( + final String tenant) + { + DictionaryRegistry result = AuthenticationUtil.runAs( + new RunAsWork() + { + public DictionaryRegistry doWork() + { + DictionaryRegistry dictionaryRegistry = new TenantDictionaryRegistryImpl( + DictionaryDAOImpl.this, tenant); + getThreadLocal().put(tenant, dictionaryRegistry); + dictionaryRegistry.init(); + getThreadLocal().remove(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); + dictionaryRegistryCache.refresh(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/src/main/java/org/alfresco/repo/dictionary/DictionaryListener.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryListener.java new file mode 100644 index 0000000000..5c1708389b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DictionaryNamespaceComponent.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryNamespaceComponent.java new file mode 100644 index 0000000000..3bdb0b9865 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/DictionaryRegistry.java b/src/main/java/org/alfresco/repo/dictionary/DictionaryRegistry.java new file mode 100644 index 0000000000..b8686dc8c1 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/ExtendedDictionaryListener.java b/src/main/java/org/alfresco/repo/dictionary/ExtendedDictionaryListener.java new file mode 100644 index 0000000000..a7752ef788 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/Facetable.java b/src/main/java/org/alfresco/repo/dictionary/Facetable.java new file mode 100644 index 0000000000..98fe2383ab --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java b/src/main/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java new file mode 100644 index 0000000000..1b53a5374f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2AnonymousTypeDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2AnonymousTypeDefinition.java new file mode 100644 index 0000000000..3a315ea2f5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Aspect.java b/src/main/java/org/alfresco/repo/dictionary/M2Aspect.java new file mode 100644 index 0000000000..9442dea03a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2AspectDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2AspectDefinition.java new file mode 100644 index 0000000000..834f92bc95 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Association.java b/src/main/java/org/alfresco/repo/dictionary/M2Association.java new file mode 100644 index 0000000000..ce70e64177 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2AssociationDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2AssociationDefinition.java new file mode 100644 index 0000000000..167791a1a2 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociation.java b/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociation.java new file mode 100644 index 0000000000..fce0f423f2 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociationDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociationDefinition.java new file mode 100644 index 0000000000..d8c2fcd320 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Class.java b/src/main/java/org/alfresco/repo/dictionary/M2Class.java new file mode 100644 index 0000000000..8bf8738c4f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ClassAssociation.java b/src/main/java/org/alfresco/repo/dictionary/M2ClassAssociation.java new file mode 100644 index 0000000000..a2c469f1af --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ClassDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2ClassDefinition.java new file mode 100644 index 0000000000..afca702a0f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Constraint.java b/src/main/java/org/alfresco/repo/dictionary/M2Constraint.java new file mode 100644 index 0000000000..11f8082753 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java new file mode 100644 index 0000000000..10da726728 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2DataType.java b/src/main/java/org/alfresco/repo/dictionary/M2DataType.java new file mode 100644 index 0000000000..4f6104aecc --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2DataTypeDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2DataTypeDefinition.java new file mode 100644 index 0000000000..bc72b140de --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Label.java b/src/main/java/org/alfresco/repo/dictionary/M2Label.java new file mode 100644 index 0000000000..e206ea296c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Model.java b/src/main/java/org/alfresco/repo/dictionary/M2Model.java new file mode 100644 index 0000000000..e11862b116 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ModelDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2ModelDefinition.java new file mode 100644 index 0000000000..a240743890 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2ModelDiff.java b/src/main/java/org/alfresco/repo/dictionary/M2ModelDiff.java new file mode 100644 index 0000000000..d734b34d28 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2NamedValue.java b/src/main/java/org/alfresco/repo/dictionary/M2NamedValue.java new file mode 100644 index 0000000000..fcd6e62567 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Namespace.java b/src/main/java/org/alfresco/repo/dictionary/M2Namespace.java new file mode 100644 index 0000000000..ef1f7f537e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java new file mode 100644 index 0000000000..245b6cab61 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Property.java b/src/main/java/org/alfresco/repo/dictionary/M2Property.java new file mode 100644 index 0000000000..f00e49f3ad --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java new file mode 100644 index 0000000000..e69a2c765a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2PropertyOverride.java b/src/main/java/org/alfresco/repo/dictionary/M2PropertyOverride.java new file mode 100644 index 0000000000..b8703961c1 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2Type.java b/src/main/java/org/alfresco/repo/dictionary/M2Type.java new file mode 100644 index 0000000000..50df31f6b7 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2TypeDefinition.java b/src/main/java/org/alfresco/repo/dictionary/M2TypeDefinition.java new file mode 100644 index 0000000000..88b64e1990 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/M2XML.java b/src/main/java/org/alfresco/repo/dictionary/M2XML.java new file mode 100644 index 0000000000..813d06c11c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/ModelQuery.java b/src/main/java/org/alfresco/repo/dictionary/ModelQuery.java new file mode 100644 index 0000000000..d685e4a09c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/NamespaceDAO.java b/src/main/java/org/alfresco/repo/dictionary/NamespaceDAO.java new file mode 100644 index 0000000000..9a9d805508 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/TenantDictionaryRegistryImpl.java b/src/main/java/org/alfresco/repo/dictionary/TenantDictionaryRegistryImpl.java new file mode 100644 index 0000000000..5823c5e891 --- /dev/null +++ b/src/main/java/org/alfresco/repo/dictionary/TenantDictionaryRegistryImpl.java @@ -0,0 +1,259 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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(); + } + + // notify registered listeners that dictionary has been initialised (population is complete) + for (DictionaryListener dictionaryListener : dictionaryDAO.getDictionaryListeners()) + { + dictionaryListener.afterDictionaryInit(); + } + + // 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/src/main/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java new file mode 100644 index 0000000000..ca308231a5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/ConstraintRegistry.java b/src/main/java/org/alfresco/repo/dictionary/constraint/ConstraintRegistry.java new file mode 100644 index 0000000000..946a0a0943 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/ListOfValuesConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/ListOfValuesConstraint.java new file mode 100644 index 0000000000..72565ec044 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/NameChecker.java b/src/main/java/org/alfresco/repo/dictionary/constraint/NameChecker.java new file mode 100644 index 0000000000..d8cd8a84f5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/NoOpConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/NoOpConstraint.java new file mode 100644 index 0000000000..ae14340e61 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/NumericRangeConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/NumericRangeConstraint.java new file mode 100644 index 0000000000..c0f6618901 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java new file mode 100644 index 0000000000..a8721fd08a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/RegisteredConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/RegisteredConstraint.java new file mode 100644 index 0000000000..ac59c7584a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/constraint/StringLengthConstraint.java b/src/main/java/org/alfresco/repo/dictionary/constraint/StringLengthConstraint.java new file mode 100644 index 0000000000..003c921c53 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/dictionary/m2binding.xml b/src/main/java/org/alfresco/repo/dictionary/m2binding.xml new file mode 100644 index 0000000000..98fc44169f --- /dev/null +++ b/src/main/java/org/alfresco/repo/dictionary/m2binding.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/alfresco/repo/i18n/StaticMessageLookup.java b/src/main/java/org/alfresco/repo/i18n/StaticMessageLookup.java new file mode 100644 index 0000000000..b605394aa6 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/index/shard/Floc.java b/src/main/java/org/alfresco/repo/index/shard/Floc.java new file mode 100644 index 0000000000..d0e18008bf --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/index/shard/Shard.java b/src/main/java/org/alfresco/repo/index/shard/Shard.java new file mode 100644 index 0000000000..72f6f94dbe --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/index/shard/ShardInstance.java b/src/main/java/org/alfresco/repo/index/shard/ShardInstance.java new file mode 100644 index 0000000000..348602d6d2 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/index/shard/ShardMethodEnum.java b/src/main/java/org/alfresco/repo/index/shard/ShardMethodEnum.java new file mode 100644 index 0000000000..967f8df58a --- /dev/null +++ b/src/main/java/org/alfresco/repo/index/shard/ShardMethodEnum.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.index.shard; +/** + * Enum that details sharding type + * @author Andy + * @author Michael Suzuki + * + */ +public enum ShardMethodEnum +{ + MOD_ACL_ID, + ACL_ID, + DB_ID, + DATE,//Time stamp + DATE_YEAR, + DATE_MONTH, + UNKOWN; + + 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 "DATE": + shardMethodEnum = DATE; + break; + case "DATE_YEAR": + shardMethodEnum = DATE_YEAR; + break; + case "DATE_MONTH": + shardMethodEnum = DATE_MONTH; + break; + default: + shardMethodEnum = UNKOWN; + break; + } + return shardMethodEnum; + } +} diff --git a/src/main/java/org/alfresco/repo/index/shard/ShardState.java b/src/main/java/org/alfresco/repo/index/shard/ShardState.java new file mode 100644 index 0000000000..133c5bbd0d --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/index/shard/ShardStateBuilder.java b/src/main/java/org/alfresco/repo/index/shard/ShardStateBuilder.java new file mode 100644 index 0000000000..66ccb49c09 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/MLAnalysisMode.java b/src/main/java/org/alfresco/repo/search/MLAnalysisMode.java new file mode 100644 index 0000000000..4333df900e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/adaptor/lucene/AnalysisMode.java b/src/main/java/org/alfresco/repo/search/adaptor/lucene/AnalysisMode.java new file mode 100644 index 0000000000..16fc0dd9c7 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneFunction.java b/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneFunction.java new file mode 100644 index 0000000000..117e74319c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserAdaptor.java b/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserAdaptor.java new file mode 100644 index 0000000000..67f2c3f55c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserExpressionAdaptor.java b/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserExpressionAdaptor.java new file mode 100644 index 0000000000..8a1209748a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java b/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java new file mode 100644 index 0000000000..dfc1564b66 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java @@ -0,0 +1,205 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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_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/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java b/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java new file mode 100644 index 0000000000..df50966487 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java b/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java new file mode 100644 index 0000000000..a6b5ff29a5 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java @@ -0,0 +1,549 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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_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/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.g b/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.g new file mode 100644 index 0000000000..626d6fbf41 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.tokens b/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.tokens new file mode 100644 index 0000000000..4dd787013e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java b/src/main/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java new file mode 100644 index 0000000000..ef0305f707 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.g b/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.g new file mode 100644 index 0000000000..a83635a9d9 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.tokens b/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.tokens new file mode 100644 index 0000000000..729d283dc5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSLexer.java b/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSLexer.java new file mode 100644 index 0000000000..0c1c217872 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSParser.java b/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSParser.java new file mode 100644 index 0000000000..534beff0ca --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.g b/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.g new file mode 100644 index 0000000000..ec6d3388bd --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.g @@ -0,0 +1,2426 @@ +/* + * 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 + : + ( + '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/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.tokens b/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.tokens new file mode 100644 index 0000000000..421ec5be8d --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java b/src/main/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java new file mode 100644 index 0000000000..ff7aaa9ea0 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java @@ -0,0 +1,18384 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public 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: ( ( '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: ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' | '#' | F_ESC )* + { + 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 )* + loop37: + while (true) { + int alt37=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': + { + alt37=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': + { + alt37=2; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + alt37=3; + } + break; + case '_': + { + alt37=4; + } + break; + case '$': + { + alt37=5; + } + break; + case '#': + { + alt37=6; + } + break; + case '\\': + { + alt37=7; + } + break; + } + switch (alt37) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1349:17: '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:1350:19: '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:1351:19: '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:1352:19: '_' + { + 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:1353:19: '$' + { + 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:1354:19: '#' + { + 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:1355:19: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + + default : + break loop37; + } + } + + } + + 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:1359:9: () + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1360: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:1363: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:1364: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:1364:10: ( PLUS | MINUS )? + int alt38=2; + int LA38_0 = input.LA(1); + if ( (LA38_0=='+'||LA38_0=='-') ) { + 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: + { + 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:1365:10: ( ( DIGIT )+ ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) | DOT ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) ) + int alt48=2; + int LA48_0 = input.LA(1); + if ( ((LA48_0 >= '0' && LA48_0 <= '9')) ) { + alt48=1; + } + else if ( (LA48_0=='.') ) { + alt48=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 48, 0, input); + throw nvae; + } + + switch (alt48) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1366: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:1366:17: ( DIGIT )+ + int cnt39=0; + loop39: + while (true) { + int alt39=2; + int LA39_0 = input.LA(1); + if ( ((LA39_0 >= '0' && LA39_0 <= '9')) ) { + alt39=1; + } + + switch (alt39) { + 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 ( cnt39 >= 1 ) break loop39; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(39, input); + throw eee; + } + cnt39++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1367:17: ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) + int alt44=2; + int LA44_0 = input.LA(1); + if ( (LA44_0=='.') && ((input.LA(2) != '.'))) { + 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:1368: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:1369:25: ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) + int alt42=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': + { + alt42=1; + } + break; + case 'E': + case 'e': + { + alt42=2; + } + break; + default: + alt42=3; + } + switch (alt42) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1370:33: ( DIGIT )+ ( EXPONENT |{...}? => DOT |) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1370:33: ( DIGIT )+ + int cnt40=0; + loop40: + while (true) { + int alt40=2; + int LA40_0 = input.LA(1); + if ( ((LA40_0 >= '0' && LA40_0 <= '9')) ) { + 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) >= '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 ( cnt40 >= 1 ) break loop40; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(40, input); + throw eee; + } + cnt40++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1371:33: ( EXPONENT |{...}? => DOT |) + int alt41=3; + int LA41_0 = input.LA(1); + if ( (LA41_0=='E'||LA41_0=='e') ) { + alt41=1; + } + else if ( (LA41_0=='.') && ((input.LA(2) != '.'))) { + alt41=2; + } + + switch (alt41) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1372: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:1375: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:1393: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:1396: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:1399: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:1402:25: ( EXPONENT |) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1402:25: ( EXPONENT |) + int alt43=2; + int LA43_0 = input.LA(1); + if ( (LA43_0=='E'||LA43_0=='e') ) { + alt43=1; + } + + else { + 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:1403: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:1406: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:1412: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:1413:17: ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) + int alt47=3; + int LA47_0 = input.LA(1); + if ( ((LA47_0 >= '0' && LA47_0 <= '9')) ) { + alt47=1; + } + else if ( (LA47_0=='.') && ((input.LA(2) != '.'))) { + alt47=2; + } + + switch (alt47) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1414:25: ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1414:25: ( DIGIT )+ + int cnt45=0; + loop45: + while (true) { + int alt45=2; + int LA45_0 = input.LA(1); + if ( ((LA45_0 >= '0' && LA45_0 <= '9')) ) { + 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: + { + 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 ( cnt45 >= 1 ) break loop45; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(45, input); + throw eee; + } + cnt45++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1415:25: ( EXPONENT |{...}?{...}? => DOT |) + int alt46=3; + int LA46_0 = input.LA(1); + if ( (LA46_0=='E'||LA46_0=='e') ) { + alt46=1; + } + else if ( (LA46_0=='.') && ((input.LA(2) != '.'))) { + alt46=2; + } + + switch (alt46) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1416: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:1419: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:1434: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:1438: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:1441: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:1470:9: ( ZERO_DIGIT | NON_ZERO_DIGIT ( DIGIT )* ) + int alt50=2; + int LA50_0 = input.LA(1); + if ( (LA50_0=='0') ) { + alt50=1; + } + else if ( ((LA50_0 >= '1' && LA50_0 <= '9')) ) { + 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:1471: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:1472: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:1472:26: ( DIGIT )* + loop49: + while (true) { + int alt49=2; + int LA49_0 = input.LA(1); + if ( ((LA49_0 >= '0' && LA49_0 <= '9')) ) { + 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: + { + 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 loop49; + } + } + + } + 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:1474: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:1481:9: ( '0' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1482: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:1487: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:1493: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:1502:9: ( E SIGNED_INTEGER ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1503: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:1508:9: ( ( PLUS | MINUS )? ( DIGIT )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1509:9: ( PLUS | MINUS )? ( DIGIT )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1509:9: ( PLUS | MINUS )? + int alt51=2; + int LA51_0 = input.LA(1); + if ( (LA51_0=='+'||LA51_0=='-') ) { + 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)=='+'||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:1513:9: ( DIGIT )+ + int cnt52=0; + loop52: + while (true) { + int alt52=2; + int LA52_0 = input.LA(1); + if ( ((LA52_0 >= '0' && LA52_0 <= '9')) ) { + 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: + { + 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 ( cnt52 >= 1 ) break loop52; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(52, input); + throw eee; + } + cnt52++; + } + + } + + } + 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:1517: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:1518: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:1518:9: ( F_ESC | START_WORD ) + int alt53=2; + int LA53_0 = input.LA(1); + if ( (LA53_0=='\\') ) { + alt53=1; + } + else if ( (LA53_0=='$'||(LA53_0 >= '0' && LA53_0 <= '9')||(LA53_0 >= 'A' && LA53_0 <= 'Z')||(LA53_0 >= 'a' && LA53_0 <= 'z')||(LA53_0 >= '\u00A2' && LA53_0 <= '\u00A7')||(LA53_0 >= '\u00A9' && LA53_0 <= '\u00AA')||LA53_0=='\u00AE'||LA53_0=='\u00B0'||(LA53_0 >= '\u00B2' && LA53_0 <= '\u00B3')||(LA53_0 >= '\u00B5' && LA53_0 <= '\u00B6')||(LA53_0 >= '\u00B9' && LA53_0 <= '\u00BA')||(LA53_0 >= '\u00BC' && LA53_0 <= '\u00BE')||(LA53_0 >= '\u00C0' && LA53_0 <= '\u00D6')||(LA53_0 >= '\u00D8' && LA53_0 <= '\u00F6')||(LA53_0 >= '\u00F8' && LA53_0 <= '\u0236')||(LA53_0 >= '\u0250' && LA53_0 <= '\u02C1')||(LA53_0 >= '\u02C6' && LA53_0 <= '\u02D1')||(LA53_0 >= '\u02E0' && LA53_0 <= '\u02E4')||LA53_0=='\u02EE'||(LA53_0 >= '\u0300' && LA53_0 <= '\u0357')||(LA53_0 >= '\u035D' && LA53_0 <= '\u036F')||LA53_0=='\u037A'||LA53_0=='\u0386'||(LA53_0 >= '\u0388' && LA53_0 <= '\u038A')||LA53_0=='\u038C'||(LA53_0 >= '\u038E' && LA53_0 <= '\u03A1')||(LA53_0 >= '\u03A3' && LA53_0 <= '\u03CE')||(LA53_0 >= '\u03D0' && LA53_0 <= '\u03F5')||(LA53_0 >= '\u03F7' && LA53_0 <= '\u03FB')||(LA53_0 >= '\u0400' && LA53_0 <= '\u0486')||(LA53_0 >= '\u0488' && LA53_0 <= '\u04CE')||(LA53_0 >= '\u04D0' && LA53_0 <= '\u04F5')||(LA53_0 >= '\u04F8' && LA53_0 <= '\u04F9')||(LA53_0 >= '\u0500' && LA53_0 <= '\u050F')||(LA53_0 >= '\u0531' && LA53_0 <= '\u0556')||LA53_0=='\u0559'||(LA53_0 >= '\u0561' && LA53_0 <= '\u0587')||(LA53_0 >= '\u0591' && LA53_0 <= '\u05A1')||(LA53_0 >= '\u05A3' && LA53_0 <= '\u05B9')||(LA53_0 >= '\u05BB' && LA53_0 <= '\u05BD')||LA53_0=='\u05BF'||(LA53_0 >= '\u05C1' && LA53_0 <= '\u05C2')||LA53_0=='\u05C4'||(LA53_0 >= '\u05D0' && LA53_0 <= '\u05EA')||(LA53_0 >= '\u05F0' && LA53_0 <= '\u05F2')||(LA53_0 >= '\u060E' && LA53_0 <= '\u0615')||(LA53_0 >= '\u0621' && LA53_0 <= '\u063A')||(LA53_0 >= '\u0640' && LA53_0 <= '\u0658')||(LA53_0 >= '\u0660' && LA53_0 <= '\u0669')||(LA53_0 >= '\u066E' && LA53_0 <= '\u06D3')||(LA53_0 >= '\u06D5' && LA53_0 <= '\u06DC')||(LA53_0 >= '\u06DE' && LA53_0 <= '\u06FF')||(LA53_0 >= '\u0710' && LA53_0 <= '\u074A')||(LA53_0 >= '\u074D' && LA53_0 <= '\u074F')||(LA53_0 >= '\u0780' && LA53_0 <= '\u07B1')||(LA53_0 >= '\u0901' && LA53_0 <= '\u0939')||(LA53_0 >= '\u093C' && LA53_0 <= '\u094D')||(LA53_0 >= '\u0950' && LA53_0 <= '\u0954')||(LA53_0 >= '\u0958' && LA53_0 <= '\u0963')||(LA53_0 >= '\u0966' && LA53_0 <= '\u096F')||(LA53_0 >= '\u0981' && LA53_0 <= '\u0983')||(LA53_0 >= '\u0985' && LA53_0 <= '\u098C')||(LA53_0 >= '\u098F' && LA53_0 <= '\u0990')||(LA53_0 >= '\u0993' && LA53_0 <= '\u09A8')||(LA53_0 >= '\u09AA' && LA53_0 <= '\u09B0')||LA53_0=='\u09B2'||(LA53_0 >= '\u09B6' && LA53_0 <= '\u09B9')||(LA53_0 >= '\u09BC' && LA53_0 <= '\u09C4')||(LA53_0 >= '\u09C7' && LA53_0 <= '\u09C8')||(LA53_0 >= '\u09CB' && LA53_0 <= '\u09CD')||LA53_0=='\u09D7'||(LA53_0 >= '\u09DC' && LA53_0 <= '\u09DD')||(LA53_0 >= '\u09DF' && LA53_0 <= '\u09E3')||(LA53_0 >= '\u09E6' && LA53_0 <= '\u09FA')||(LA53_0 >= '\u0A01' && LA53_0 <= '\u0A03')||(LA53_0 >= '\u0A05' && LA53_0 <= '\u0A0A')||(LA53_0 >= '\u0A0F' && LA53_0 <= '\u0A10')||(LA53_0 >= '\u0A13' && LA53_0 <= '\u0A28')||(LA53_0 >= '\u0A2A' && LA53_0 <= '\u0A30')||(LA53_0 >= '\u0A32' && LA53_0 <= '\u0A33')||(LA53_0 >= '\u0A35' && LA53_0 <= '\u0A36')||(LA53_0 >= '\u0A38' && LA53_0 <= '\u0A39')||LA53_0=='\u0A3C'||(LA53_0 >= '\u0A3E' && LA53_0 <= '\u0A42')||(LA53_0 >= '\u0A47' && LA53_0 <= '\u0A48')||(LA53_0 >= '\u0A4B' && LA53_0 <= '\u0A4D')||(LA53_0 >= '\u0A59' && LA53_0 <= '\u0A5C')||LA53_0=='\u0A5E'||(LA53_0 >= '\u0A66' && LA53_0 <= '\u0A74')||(LA53_0 >= '\u0A81' && LA53_0 <= '\u0A83')||(LA53_0 >= '\u0A85' && LA53_0 <= '\u0A8D')||(LA53_0 >= '\u0A8F' && LA53_0 <= '\u0A91')||(LA53_0 >= '\u0A93' && LA53_0 <= '\u0AA8')||(LA53_0 >= '\u0AAA' && LA53_0 <= '\u0AB0')||(LA53_0 >= '\u0AB2' && LA53_0 <= '\u0AB3')||(LA53_0 >= '\u0AB5' && LA53_0 <= '\u0AB9')||(LA53_0 >= '\u0ABC' && LA53_0 <= '\u0AC5')||(LA53_0 >= '\u0AC7' && LA53_0 <= '\u0AC9')||(LA53_0 >= '\u0ACB' && LA53_0 <= '\u0ACD')||LA53_0=='\u0AD0'||(LA53_0 >= '\u0AE0' && LA53_0 <= '\u0AE3')||(LA53_0 >= '\u0AE6' && LA53_0 <= '\u0AEF')||LA53_0=='\u0AF1'||(LA53_0 >= '\u0B01' && LA53_0 <= '\u0B03')||(LA53_0 >= '\u0B05' && LA53_0 <= '\u0B0C')||(LA53_0 >= '\u0B0F' && LA53_0 <= '\u0B10')||(LA53_0 >= '\u0B13' && LA53_0 <= '\u0B28')||(LA53_0 >= '\u0B2A' && LA53_0 <= '\u0B30')||(LA53_0 >= '\u0B32' && LA53_0 <= '\u0B33')||(LA53_0 >= '\u0B35' && LA53_0 <= '\u0B39')||(LA53_0 >= '\u0B3C' && LA53_0 <= '\u0B43')||(LA53_0 >= '\u0B47' && LA53_0 <= '\u0B48')||(LA53_0 >= '\u0B4B' && LA53_0 <= '\u0B4D')||(LA53_0 >= '\u0B56' && LA53_0 <= '\u0B57')||(LA53_0 >= '\u0B5C' && LA53_0 <= '\u0B5D')||(LA53_0 >= '\u0B5F' && LA53_0 <= '\u0B61')||(LA53_0 >= '\u0B66' && LA53_0 <= '\u0B71')||(LA53_0 >= '\u0B82' && LA53_0 <= '\u0B83')||(LA53_0 >= '\u0B85' && LA53_0 <= '\u0B8A')||(LA53_0 >= '\u0B8E' && LA53_0 <= '\u0B90')||(LA53_0 >= '\u0B92' && LA53_0 <= '\u0B95')||(LA53_0 >= '\u0B99' && LA53_0 <= '\u0B9A')||LA53_0=='\u0B9C'||(LA53_0 >= '\u0B9E' && LA53_0 <= '\u0B9F')||(LA53_0 >= '\u0BA3' && LA53_0 <= '\u0BA4')||(LA53_0 >= '\u0BA8' && LA53_0 <= '\u0BAA')||(LA53_0 >= '\u0BAE' && LA53_0 <= '\u0BB5')||(LA53_0 >= '\u0BB7' && LA53_0 <= '\u0BB9')||(LA53_0 >= '\u0BBE' && LA53_0 <= '\u0BC2')||(LA53_0 >= '\u0BC6' && LA53_0 <= '\u0BC8')||(LA53_0 >= '\u0BCA' && LA53_0 <= '\u0BCD')||LA53_0=='\u0BD7'||(LA53_0 >= '\u0BE7' && LA53_0 <= '\u0BFA')||(LA53_0 >= '\u0C01' && LA53_0 <= '\u0C03')||(LA53_0 >= '\u0C05' && LA53_0 <= '\u0C0C')||(LA53_0 >= '\u0C0E' && LA53_0 <= '\u0C10')||(LA53_0 >= '\u0C12' && LA53_0 <= '\u0C28')||(LA53_0 >= '\u0C2A' && LA53_0 <= '\u0C33')||(LA53_0 >= '\u0C35' && LA53_0 <= '\u0C39')||(LA53_0 >= '\u0C3E' && LA53_0 <= '\u0C44')||(LA53_0 >= '\u0C46' && LA53_0 <= '\u0C48')||(LA53_0 >= '\u0C4A' && LA53_0 <= '\u0C4D')||(LA53_0 >= '\u0C55' && LA53_0 <= '\u0C56')||(LA53_0 >= '\u0C60' && LA53_0 <= '\u0C61')||(LA53_0 >= '\u0C66' && LA53_0 <= '\u0C6F')||(LA53_0 >= '\u0C82' && LA53_0 <= '\u0C83')||(LA53_0 >= '\u0C85' && LA53_0 <= '\u0C8C')||(LA53_0 >= '\u0C8E' && LA53_0 <= '\u0C90')||(LA53_0 >= '\u0C92' && LA53_0 <= '\u0CA8')||(LA53_0 >= '\u0CAA' && LA53_0 <= '\u0CB3')||(LA53_0 >= '\u0CB5' && LA53_0 <= '\u0CB9')||(LA53_0 >= '\u0CBC' && LA53_0 <= '\u0CC4')||(LA53_0 >= '\u0CC6' && LA53_0 <= '\u0CC8')||(LA53_0 >= '\u0CCA' && LA53_0 <= '\u0CCD')||(LA53_0 >= '\u0CD5' && LA53_0 <= '\u0CD6')||LA53_0=='\u0CDE'||(LA53_0 >= '\u0CE0' && LA53_0 <= '\u0CE1')||(LA53_0 >= '\u0CE6' && LA53_0 <= '\u0CEF')||(LA53_0 >= '\u0D02' && LA53_0 <= '\u0D03')||(LA53_0 >= '\u0D05' && LA53_0 <= '\u0D0C')||(LA53_0 >= '\u0D0E' && LA53_0 <= '\u0D10')||(LA53_0 >= '\u0D12' && LA53_0 <= '\u0D28')||(LA53_0 >= '\u0D2A' && LA53_0 <= '\u0D39')||(LA53_0 >= '\u0D3E' && LA53_0 <= '\u0D43')||(LA53_0 >= '\u0D46' && LA53_0 <= '\u0D48')||(LA53_0 >= '\u0D4A' && LA53_0 <= '\u0D4D')||LA53_0=='\u0D57'||(LA53_0 >= '\u0D60' && LA53_0 <= '\u0D61')||(LA53_0 >= '\u0D66' && LA53_0 <= '\u0D6F')||(LA53_0 >= '\u0D82' && LA53_0 <= '\u0D83')||(LA53_0 >= '\u0D85' && LA53_0 <= '\u0D96')||(LA53_0 >= '\u0D9A' && LA53_0 <= '\u0DB1')||(LA53_0 >= '\u0DB3' && LA53_0 <= '\u0DBB')||LA53_0=='\u0DBD'||(LA53_0 >= '\u0DC0' && LA53_0 <= '\u0DC6')||LA53_0=='\u0DCA'||(LA53_0 >= '\u0DCF' && LA53_0 <= '\u0DD4')||LA53_0=='\u0DD6'||(LA53_0 >= '\u0DD8' && LA53_0 <= '\u0DDF')||(LA53_0 >= '\u0DF2' && LA53_0 <= '\u0DF3')||(LA53_0 >= '\u0E01' && LA53_0 <= '\u0E3A')||(LA53_0 >= '\u0E3F' && LA53_0 <= '\u0E4E')||(LA53_0 >= '\u0E50' && LA53_0 <= '\u0E59')||(LA53_0 >= '\u0E81' && LA53_0 <= '\u0E82')||LA53_0=='\u0E84'||(LA53_0 >= '\u0E87' && LA53_0 <= '\u0E88')||LA53_0=='\u0E8A'||LA53_0=='\u0E8D'||(LA53_0 >= '\u0E94' && LA53_0 <= '\u0E97')||(LA53_0 >= '\u0E99' && LA53_0 <= '\u0E9F')||(LA53_0 >= '\u0EA1' && LA53_0 <= '\u0EA3')||LA53_0=='\u0EA5'||LA53_0=='\u0EA7'||(LA53_0 >= '\u0EAA' && LA53_0 <= '\u0EAB')||(LA53_0 >= '\u0EAD' && LA53_0 <= '\u0EB9')||(LA53_0 >= '\u0EBB' && LA53_0 <= '\u0EBD')||(LA53_0 >= '\u0EC0' && LA53_0 <= '\u0EC4')||LA53_0=='\u0EC6'||(LA53_0 >= '\u0EC8' && LA53_0 <= '\u0ECD')||(LA53_0 >= '\u0ED0' && LA53_0 <= '\u0ED9')||(LA53_0 >= '\u0EDC' && LA53_0 <= '\u0EDD')||(LA53_0 >= '\u0F00' && LA53_0 <= '\u0F03')||(LA53_0 >= '\u0F13' && LA53_0 <= '\u0F39')||(LA53_0 >= '\u0F3E' && LA53_0 <= '\u0F47')||(LA53_0 >= '\u0F49' && LA53_0 <= '\u0F6A')||(LA53_0 >= '\u0F71' && LA53_0 <= '\u0F84')||(LA53_0 >= '\u0F86' && LA53_0 <= '\u0F8B')||(LA53_0 >= '\u0F90' && LA53_0 <= '\u0F97')||(LA53_0 >= '\u0F99' && LA53_0 <= '\u0FBC')||(LA53_0 >= '\u0FBE' && LA53_0 <= '\u0FCC')||LA53_0=='\u0FCF'||(LA53_0 >= '\u1000' && LA53_0 <= '\u1021')||(LA53_0 >= '\u1023' && LA53_0 <= '\u1027')||(LA53_0 >= '\u1029' && LA53_0 <= '\u102A')||(LA53_0 >= '\u102C' && LA53_0 <= '\u1032')||(LA53_0 >= '\u1036' && LA53_0 <= '\u1039')||(LA53_0 >= '\u1040' && LA53_0 <= '\u1049')||(LA53_0 >= '\u1050' && LA53_0 <= '\u1059')||(LA53_0 >= '\u10A0' && LA53_0 <= '\u10C5')||(LA53_0 >= '\u10D0' && LA53_0 <= '\u10F8')||(LA53_0 >= '\u1100' && LA53_0 <= '\u1159')||(LA53_0 >= '\u115F' && LA53_0 <= '\u11A2')||(LA53_0 >= '\u11A8' && LA53_0 <= '\u11F9')||(LA53_0 >= '\u1200' && LA53_0 <= '\u1206')||(LA53_0 >= '\u1208' && LA53_0 <= '\u1246')||LA53_0=='\u1248'||(LA53_0 >= '\u124A' && LA53_0 <= '\u124D')||(LA53_0 >= '\u1250' && LA53_0 <= '\u1256')||LA53_0=='\u1258'||(LA53_0 >= '\u125A' && LA53_0 <= '\u125D')||(LA53_0 >= '\u1260' && LA53_0 <= '\u1286')||LA53_0=='\u1288'||(LA53_0 >= '\u128A' && LA53_0 <= '\u128D')||(LA53_0 >= '\u1290' && LA53_0 <= '\u12AE')||LA53_0=='\u12B0'||(LA53_0 >= '\u12B2' && LA53_0 <= '\u12B5')||(LA53_0 >= '\u12B8' && LA53_0 <= '\u12BE')||LA53_0=='\u12C0'||(LA53_0 >= '\u12C2' && LA53_0 <= '\u12C5')||(LA53_0 >= '\u12C8' && LA53_0 <= '\u12CE')||(LA53_0 >= '\u12D0' && LA53_0 <= '\u12D6')||(LA53_0 >= '\u12D8' && LA53_0 <= '\u12EE')||(LA53_0 >= '\u12F0' && LA53_0 <= '\u130E')||LA53_0=='\u1310'||(LA53_0 >= '\u1312' && LA53_0 <= '\u1315')||(LA53_0 >= '\u1318' && LA53_0 <= '\u131E')||(LA53_0 >= '\u1320' && LA53_0 <= '\u1346')||(LA53_0 >= '\u1348' && LA53_0 <= '\u135A')||(LA53_0 >= '\u1369' && LA53_0 <= '\u137C')||(LA53_0 >= '\u13A0' && LA53_0 <= '\u13F4')||(LA53_0 >= '\u1401' && LA53_0 <= '\u166C')||(LA53_0 >= '\u166F' && LA53_0 <= '\u1676')||(LA53_0 >= '\u1681' && LA53_0 <= '\u169A')||(LA53_0 >= '\u16A0' && LA53_0 <= '\u16EA')||(LA53_0 >= '\u16EE' && LA53_0 <= '\u16F0')||(LA53_0 >= '\u1700' && LA53_0 <= '\u170C')||(LA53_0 >= '\u170E' && LA53_0 <= '\u1714')||(LA53_0 >= '\u1720' && LA53_0 <= '\u1734')||(LA53_0 >= '\u1740' && LA53_0 <= '\u1753')||(LA53_0 >= '\u1760' && LA53_0 <= '\u176C')||(LA53_0 >= '\u176E' && LA53_0 <= '\u1770')||(LA53_0 >= '\u1772' && LA53_0 <= '\u1773')||(LA53_0 >= '\u1780' && LA53_0 <= '\u17B3')||(LA53_0 >= '\u17B6' && LA53_0 <= '\u17D3')||LA53_0=='\u17D7'||(LA53_0 >= '\u17DB' && LA53_0 <= '\u17DD')||(LA53_0 >= '\u17E0' && LA53_0 <= '\u17E9')||(LA53_0 >= '\u17F0' && LA53_0 <= '\u17F9')||(LA53_0 >= '\u180B' && LA53_0 <= '\u180D')||(LA53_0 >= '\u1810' && LA53_0 <= '\u1819')||(LA53_0 >= '\u1820' && LA53_0 <= '\u1877')||(LA53_0 >= '\u1880' && LA53_0 <= '\u18A9')||(LA53_0 >= '\u1900' && LA53_0 <= '\u191C')||(LA53_0 >= '\u1920' && LA53_0 <= '\u192B')||(LA53_0 >= '\u1930' && LA53_0 <= '\u193B')||LA53_0=='\u1940'||(LA53_0 >= '\u1946' && LA53_0 <= '\u196D')||(LA53_0 >= '\u1970' && LA53_0 <= '\u1974')||(LA53_0 >= '\u19E0' && LA53_0 <= '\u19FF')||(LA53_0 >= '\u1D00' && LA53_0 <= '\u1D6B')||(LA53_0 >= '\u1E00' && LA53_0 <= '\u1E9B')||(LA53_0 >= '\u1EA0' && LA53_0 <= '\u1EF9')||(LA53_0 >= '\u1F00' && LA53_0 <= '\u1F15')||(LA53_0 >= '\u1F18' && LA53_0 <= '\u1F1D')||(LA53_0 >= '\u1F20' && LA53_0 <= '\u1F45')||(LA53_0 >= '\u1F48' && LA53_0 <= '\u1F4D')||(LA53_0 >= '\u1F50' && LA53_0 <= '\u1F57')||LA53_0=='\u1F59'||LA53_0=='\u1F5B'||LA53_0=='\u1F5D'||(LA53_0 >= '\u1F5F' && LA53_0 <= '\u1F7D')||(LA53_0 >= '\u1F80' && LA53_0 <= '\u1FB4')||(LA53_0 >= '\u1FB6' && LA53_0 <= '\u1FBC')||LA53_0=='\u1FBE'||(LA53_0 >= '\u1FC2' && LA53_0 <= '\u1FC4')||(LA53_0 >= '\u1FC6' && LA53_0 <= '\u1FCC')||(LA53_0 >= '\u1FD0' && LA53_0 <= '\u1FD3')||(LA53_0 >= '\u1FD6' && LA53_0 <= '\u1FDB')||(LA53_0 >= '\u1FE0' && LA53_0 <= '\u1FEC')||(LA53_0 >= '\u1FF2' && LA53_0 <= '\u1FF4')||(LA53_0 >= '\u1FF6' && LA53_0 <= '\u1FFC')||(LA53_0 >= '\u2070' && LA53_0 <= '\u2071')||(LA53_0 >= '\u2074' && LA53_0 <= '\u2079')||(LA53_0 >= '\u207F' && LA53_0 <= '\u2089')||(LA53_0 >= '\u20A0' && LA53_0 <= '\u20B1')||(LA53_0 >= '\u20D0' && LA53_0 <= '\u20EA')||(LA53_0 >= '\u2100' && LA53_0 <= '\u213B')||(LA53_0 >= '\u213D' && LA53_0 <= '\u213F')||(LA53_0 >= '\u2145' && LA53_0 <= '\u214A')||(LA53_0 >= '\u2153' && LA53_0 <= '\u2183')||(LA53_0 >= '\u2195' && LA53_0 <= '\u2199')||(LA53_0 >= '\u219C' && LA53_0 <= '\u219F')||(LA53_0 >= '\u21A1' && LA53_0 <= '\u21A2')||(LA53_0 >= '\u21A4' && LA53_0 <= '\u21A5')||(LA53_0 >= '\u21A7' && LA53_0 <= '\u21AD')||(LA53_0 >= '\u21AF' && LA53_0 <= '\u21CD')||(LA53_0 >= '\u21D0' && LA53_0 <= '\u21D1')||LA53_0=='\u21D3'||(LA53_0 >= '\u21D5' && LA53_0 <= '\u21F3')||(LA53_0 >= '\u2300' && LA53_0 <= '\u2307')||(LA53_0 >= '\u230C' && LA53_0 <= '\u231F')||(LA53_0 >= '\u2322' && LA53_0 <= '\u2328')||(LA53_0 >= '\u232B' && LA53_0 <= '\u237B')||(LA53_0 >= '\u237D' && LA53_0 <= '\u239A')||(LA53_0 >= '\u23B7' && LA53_0 <= '\u23D0')||(LA53_0 >= '\u2400' && LA53_0 <= '\u2426')||(LA53_0 >= '\u2440' && LA53_0 <= '\u244A')||(LA53_0 >= '\u2460' && LA53_0 <= '\u25B6')||(LA53_0 >= '\u25B8' && LA53_0 <= '\u25C0')||(LA53_0 >= '\u25C2' && LA53_0 <= '\u25F7')||(LA53_0 >= '\u2600' && LA53_0 <= '\u2617')||(LA53_0 >= '\u2619' && LA53_0 <= '\u266E')||(LA53_0 >= '\u2670' && LA53_0 <= '\u267D')||(LA53_0 >= '\u2680' && LA53_0 <= '\u2691')||(LA53_0 >= '\u26A0' && LA53_0 <= '\u26A1')||(LA53_0 >= '\u2701' && LA53_0 <= '\u2704')||(LA53_0 >= '\u2706' && LA53_0 <= '\u2709')||(LA53_0 >= '\u270C' && LA53_0 <= '\u2727')||(LA53_0 >= '\u2729' && LA53_0 <= '\u274B')||LA53_0=='\u274D'||(LA53_0 >= '\u274F' && LA53_0 <= '\u2752')||LA53_0=='\u2756'||(LA53_0 >= '\u2758' && LA53_0 <= '\u275E')||(LA53_0 >= '\u2761' && LA53_0 <= '\u2767')||(LA53_0 >= '\u2776' && LA53_0 <= '\u2794')||(LA53_0 >= '\u2798' && LA53_0 <= '\u27AF')||(LA53_0 >= '\u27B1' && LA53_0 <= '\u27BE')||(LA53_0 >= '\u2800' && LA53_0 <= '\u28FF')||(LA53_0 >= '\u2B00' && LA53_0 <= '\u2B0D')||(LA53_0 >= '\u2E80' && LA53_0 <= '\u2E99')||(LA53_0 >= '\u2E9B' && LA53_0 <= '\u2EF3')||(LA53_0 >= '\u2F00' && LA53_0 <= '\u2FD5')||(LA53_0 >= '\u2FF0' && LA53_0 <= '\u2FFB')||(LA53_0 >= '\u3004' && LA53_0 <= '\u3007')||(LA53_0 >= '\u3012' && LA53_0 <= '\u3013')||(LA53_0 >= '\u3020' && LA53_0 <= '\u302F')||(LA53_0 >= '\u3031' && LA53_0 <= '\u303C')||(LA53_0 >= '\u303E' && LA53_0 <= '\u303F')||(LA53_0 >= '\u3041' && LA53_0 <= '\u3096')||(LA53_0 >= '\u3099' && LA53_0 <= '\u309A')||(LA53_0 >= '\u309D' && LA53_0 <= '\u309F')||(LA53_0 >= '\u30A1' && LA53_0 <= '\u30FA')||(LA53_0 >= '\u30FC' && LA53_0 <= '\u30FF')||(LA53_0 >= '\u3105' && LA53_0 <= '\u312C')||(LA53_0 >= '\u3131' && LA53_0 <= '\u318E')||(LA53_0 >= '\u3190' && LA53_0 <= '\u31B7')||(LA53_0 >= '\u31F0' && LA53_0 <= '\u321E')||(LA53_0 >= '\u3220' && LA53_0 <= '\u3243')||(LA53_0 >= '\u3250' && LA53_0 <= '\u327D')||(LA53_0 >= '\u327F' && LA53_0 <= '\u32FE')||(LA53_0 >= '\u3300' && LA53_0 <= '\u4DB5')||(LA53_0 >= '\u4DC0' && LA53_0 <= '\u9FA5')||(LA53_0 >= '\uA000' && LA53_0 <= '\uA48C')||(LA53_0 >= '\uA490' && LA53_0 <= '\uA4C6')||(LA53_0 >= '\uAC00' && LA53_0 <= '\uD7A3')||(LA53_0 >= '\uF900' && LA53_0 <= '\uFA2D')||(LA53_0 >= '\uFA30' && LA53_0 <= '\uFA6A')||(LA53_0 >= '\uFB00' && LA53_0 <= '\uFB06')||(LA53_0 >= '\uFB13' && LA53_0 <= '\uFB17')||(LA53_0 >= '\uFB1D' && LA53_0 <= '\uFB28')||(LA53_0 >= '\uFB2A' && LA53_0 <= '\uFB36')||(LA53_0 >= '\uFB38' && LA53_0 <= '\uFB3C')||LA53_0=='\uFB3E'||(LA53_0 >= '\uFB40' && LA53_0 <= '\uFB41')||(LA53_0 >= '\uFB43' && LA53_0 <= '\uFB44')||(LA53_0 >= '\uFB46' && LA53_0 <= '\uFBB1')||(LA53_0 >= '\uFBD3' && LA53_0 <= '\uFD3D')||(LA53_0 >= '\uFD50' && LA53_0 <= '\uFD8F')||(LA53_0 >= '\uFD92' && LA53_0 <= '\uFDC7')||(LA53_0 >= '\uFDF0' && LA53_0 <= '\uFDFD')||(LA53_0 >= '\uFE00' && LA53_0 <= '\uFE0F')||(LA53_0 >= '\uFE20' && LA53_0 <= '\uFE23')||LA53_0=='\uFE69'||(LA53_0 >= '\uFE70' && LA53_0 <= '\uFE74')||(LA53_0 >= '\uFE76' && LA53_0 <= '\uFEFC')||LA53_0=='\uFF04'||(LA53_0 >= '\uFF10' && LA53_0 <= '\uFF19')||(LA53_0 >= '\uFF21' && LA53_0 <= '\uFF3A')||(LA53_0 >= '\uFF41' && LA53_0 <= '\uFF5A')||(LA53_0 >= '\uFF66' && LA53_0 <= '\uFFBE')||(LA53_0 >= '\uFFC2' && LA53_0 <= '\uFFC7')||(LA53_0 >= '\uFFCA' && LA53_0 <= '\uFFCF')||(LA53_0 >= '\uFFD2' && LA53_0 <= '\uFFD7')||(LA53_0 >= '\uFFDA' && LA53_0 <= '\uFFDC')||(LA53_0 >= '\uFFE0' && LA53_0 <= '\uFFE1')||(LA53_0 >= '\uFFE4' && LA53_0 <= '\uFFE6')||LA53_0=='\uFFE8'||(LA53_0 >= '\uFFED' && LA53_0 <= '\uFFEE')) ) { + alt53=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + 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:1519: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:1520: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:1522:9: ( F_ESC | IN_WORD )* + loop54: + while (true) { + int alt54=3; + int LA54_0 = input.LA(1); + if ( (LA54_0=='\\') ) { + alt54=1; + } + else if ( ((LA54_0 >= '!' && LA54_0 <= '\'')||LA54_0=='+'||LA54_0=='-'||(LA54_0 >= '/' && LA54_0 <= '9')||LA54_0==';'||LA54_0=='='||(LA54_0 >= '@' && LA54_0 <= 'Z')||LA54_0=='_'||(LA54_0 >= 'a' && LA54_0 <= 'z')||LA54_0=='|'||(LA54_0 >= '\u00A1' && LA54_0 <= '\u00A7')||(LA54_0 >= '\u00A9' && LA54_0 <= '\u00AA')||LA54_0=='\u00AC'||LA54_0=='\u00AE'||(LA54_0 >= '\u00B0' && LA54_0 <= '\u00B3')||(LA54_0 >= '\u00B5' && LA54_0 <= '\u00B7')||(LA54_0 >= '\u00B9' && LA54_0 <= '\u00BA')||(LA54_0 >= '\u00BC' && LA54_0 <= '\u0236')||(LA54_0 >= '\u0250' && LA54_0 <= '\u02C1')||(LA54_0 >= '\u02C6' && LA54_0 <= '\u02D1')||(LA54_0 >= '\u02E0' && LA54_0 <= '\u02E4')||LA54_0=='\u02EE'||(LA54_0 >= '\u0300' && LA54_0 <= '\u0357')||(LA54_0 >= '\u035D' && LA54_0 <= '\u036F')||LA54_0=='\u037A'||LA54_0=='\u037E'||(LA54_0 >= '\u0386' && LA54_0 <= '\u038A')||LA54_0=='\u038C'||(LA54_0 >= '\u038E' && LA54_0 <= '\u03A1')||(LA54_0 >= '\u03A3' && LA54_0 <= '\u03CE')||(LA54_0 >= '\u03D0' && LA54_0 <= '\u03FB')||(LA54_0 >= '\u0400' && LA54_0 <= '\u0486')||(LA54_0 >= '\u0488' && LA54_0 <= '\u04CE')||(LA54_0 >= '\u04D0' && LA54_0 <= '\u04F5')||(LA54_0 >= '\u04F8' && LA54_0 <= '\u04F9')||(LA54_0 >= '\u0500' && LA54_0 <= '\u050F')||(LA54_0 >= '\u0531' && LA54_0 <= '\u0556')||(LA54_0 >= '\u0559' && LA54_0 <= '\u055F')||(LA54_0 >= '\u0561' && LA54_0 <= '\u0587')||(LA54_0 >= '\u0589' && LA54_0 <= '\u058A')||(LA54_0 >= '\u0591' && LA54_0 <= '\u05A1')||(LA54_0 >= '\u05A3' && LA54_0 <= '\u05B9')||(LA54_0 >= '\u05BB' && LA54_0 <= '\u05C4')||(LA54_0 >= '\u05D0' && LA54_0 <= '\u05EA')||(LA54_0 >= '\u05F0' && LA54_0 <= '\u05F4')||(LA54_0 >= '\u060C' && LA54_0 <= '\u0615')||LA54_0=='\u061B'||LA54_0=='\u061F'||(LA54_0 >= '\u0621' && LA54_0 <= '\u063A')||(LA54_0 >= '\u0640' && LA54_0 <= '\u0658')||(LA54_0 >= '\u0660' && LA54_0 <= '\u06DC')||(LA54_0 >= '\u06DE' && LA54_0 <= '\u070D')||(LA54_0 >= '\u0710' && LA54_0 <= '\u074A')||(LA54_0 >= '\u074D' && LA54_0 <= '\u074F')||(LA54_0 >= '\u0780' && LA54_0 <= '\u07B1')||(LA54_0 >= '\u0901' && LA54_0 <= '\u0939')||(LA54_0 >= '\u093C' && LA54_0 <= '\u094D')||(LA54_0 >= '\u0950' && LA54_0 <= '\u0954')||(LA54_0 >= '\u0958' && LA54_0 <= '\u0970')||(LA54_0 >= '\u0981' && LA54_0 <= '\u0983')||(LA54_0 >= '\u0985' && LA54_0 <= '\u098C')||(LA54_0 >= '\u098F' && LA54_0 <= '\u0990')||(LA54_0 >= '\u0993' && LA54_0 <= '\u09A8')||(LA54_0 >= '\u09AA' && LA54_0 <= '\u09B0')||LA54_0=='\u09B2'||(LA54_0 >= '\u09B6' && LA54_0 <= '\u09B9')||(LA54_0 >= '\u09BC' && LA54_0 <= '\u09C4')||(LA54_0 >= '\u09C7' && LA54_0 <= '\u09C8')||(LA54_0 >= '\u09CB' && LA54_0 <= '\u09CD')||LA54_0=='\u09D7'||(LA54_0 >= '\u09DC' && LA54_0 <= '\u09DD')||(LA54_0 >= '\u09DF' && LA54_0 <= '\u09E3')||(LA54_0 >= '\u09E6' && LA54_0 <= '\u09FA')||(LA54_0 >= '\u0A01' && LA54_0 <= '\u0A03')||(LA54_0 >= '\u0A05' && LA54_0 <= '\u0A0A')||(LA54_0 >= '\u0A0F' && LA54_0 <= '\u0A10')||(LA54_0 >= '\u0A13' && LA54_0 <= '\u0A28')||(LA54_0 >= '\u0A2A' && LA54_0 <= '\u0A30')||(LA54_0 >= '\u0A32' && LA54_0 <= '\u0A33')||(LA54_0 >= '\u0A35' && LA54_0 <= '\u0A36')||(LA54_0 >= '\u0A38' && LA54_0 <= '\u0A39')||LA54_0=='\u0A3C'||(LA54_0 >= '\u0A3E' && LA54_0 <= '\u0A42')||(LA54_0 >= '\u0A47' && LA54_0 <= '\u0A48')||(LA54_0 >= '\u0A4B' && LA54_0 <= '\u0A4D')||(LA54_0 >= '\u0A59' && LA54_0 <= '\u0A5C')||LA54_0=='\u0A5E'||(LA54_0 >= '\u0A66' && LA54_0 <= '\u0A74')||(LA54_0 >= '\u0A81' && LA54_0 <= '\u0A83')||(LA54_0 >= '\u0A85' && LA54_0 <= '\u0A8D')||(LA54_0 >= '\u0A8F' && LA54_0 <= '\u0A91')||(LA54_0 >= '\u0A93' && LA54_0 <= '\u0AA8')||(LA54_0 >= '\u0AAA' && LA54_0 <= '\u0AB0')||(LA54_0 >= '\u0AB2' && LA54_0 <= '\u0AB3')||(LA54_0 >= '\u0AB5' && LA54_0 <= '\u0AB9')||(LA54_0 >= '\u0ABC' && LA54_0 <= '\u0AC5')||(LA54_0 >= '\u0AC7' && LA54_0 <= '\u0AC9')||(LA54_0 >= '\u0ACB' && LA54_0 <= '\u0ACD')||LA54_0=='\u0AD0'||(LA54_0 >= '\u0AE0' && LA54_0 <= '\u0AE3')||(LA54_0 >= '\u0AE6' && LA54_0 <= '\u0AEF')||LA54_0=='\u0AF1'||(LA54_0 >= '\u0B01' && LA54_0 <= '\u0B03')||(LA54_0 >= '\u0B05' && LA54_0 <= '\u0B0C')||(LA54_0 >= '\u0B0F' && LA54_0 <= '\u0B10')||(LA54_0 >= '\u0B13' && LA54_0 <= '\u0B28')||(LA54_0 >= '\u0B2A' && LA54_0 <= '\u0B30')||(LA54_0 >= '\u0B32' && LA54_0 <= '\u0B33')||(LA54_0 >= '\u0B35' && LA54_0 <= '\u0B39')||(LA54_0 >= '\u0B3C' && LA54_0 <= '\u0B43')||(LA54_0 >= '\u0B47' && LA54_0 <= '\u0B48')||(LA54_0 >= '\u0B4B' && LA54_0 <= '\u0B4D')||(LA54_0 >= '\u0B56' && LA54_0 <= '\u0B57')||(LA54_0 >= '\u0B5C' && LA54_0 <= '\u0B5D')||(LA54_0 >= '\u0B5F' && LA54_0 <= '\u0B61')||(LA54_0 >= '\u0B66' && LA54_0 <= '\u0B71')||(LA54_0 >= '\u0B82' && LA54_0 <= '\u0B83')||(LA54_0 >= '\u0B85' && LA54_0 <= '\u0B8A')||(LA54_0 >= '\u0B8E' && LA54_0 <= '\u0B90')||(LA54_0 >= '\u0B92' && LA54_0 <= '\u0B95')||(LA54_0 >= '\u0B99' && LA54_0 <= '\u0B9A')||LA54_0=='\u0B9C'||(LA54_0 >= '\u0B9E' && LA54_0 <= '\u0B9F')||(LA54_0 >= '\u0BA3' && LA54_0 <= '\u0BA4')||(LA54_0 >= '\u0BA8' && LA54_0 <= '\u0BAA')||(LA54_0 >= '\u0BAE' && LA54_0 <= '\u0BB5')||(LA54_0 >= '\u0BB7' && LA54_0 <= '\u0BB9')||(LA54_0 >= '\u0BBE' && LA54_0 <= '\u0BC2')||(LA54_0 >= '\u0BC6' && LA54_0 <= '\u0BC8')||(LA54_0 >= '\u0BCA' && LA54_0 <= '\u0BCD')||LA54_0=='\u0BD7'||(LA54_0 >= '\u0BE7' && LA54_0 <= '\u0BFA')||(LA54_0 >= '\u0C01' && LA54_0 <= '\u0C03')||(LA54_0 >= '\u0C05' && LA54_0 <= '\u0C0C')||(LA54_0 >= '\u0C0E' && LA54_0 <= '\u0C10')||(LA54_0 >= '\u0C12' && LA54_0 <= '\u0C28')||(LA54_0 >= '\u0C2A' && LA54_0 <= '\u0C33')||(LA54_0 >= '\u0C35' && LA54_0 <= '\u0C39')||(LA54_0 >= '\u0C3E' && LA54_0 <= '\u0C44')||(LA54_0 >= '\u0C46' && LA54_0 <= '\u0C48')||(LA54_0 >= '\u0C4A' && LA54_0 <= '\u0C4D')||(LA54_0 >= '\u0C55' && LA54_0 <= '\u0C56')||(LA54_0 >= '\u0C60' && LA54_0 <= '\u0C61')||(LA54_0 >= '\u0C66' && LA54_0 <= '\u0C6F')||(LA54_0 >= '\u0C82' && LA54_0 <= '\u0C83')||(LA54_0 >= '\u0C85' && LA54_0 <= '\u0C8C')||(LA54_0 >= '\u0C8E' && LA54_0 <= '\u0C90')||(LA54_0 >= '\u0C92' && LA54_0 <= '\u0CA8')||(LA54_0 >= '\u0CAA' && LA54_0 <= '\u0CB3')||(LA54_0 >= '\u0CB5' && LA54_0 <= '\u0CB9')||(LA54_0 >= '\u0CBC' && LA54_0 <= '\u0CC4')||(LA54_0 >= '\u0CC6' && LA54_0 <= '\u0CC8')||(LA54_0 >= '\u0CCA' && LA54_0 <= '\u0CCD')||(LA54_0 >= '\u0CD5' && LA54_0 <= '\u0CD6')||LA54_0=='\u0CDE'||(LA54_0 >= '\u0CE0' && LA54_0 <= '\u0CE1')||(LA54_0 >= '\u0CE6' && LA54_0 <= '\u0CEF')||(LA54_0 >= '\u0D02' && LA54_0 <= '\u0D03')||(LA54_0 >= '\u0D05' && LA54_0 <= '\u0D0C')||(LA54_0 >= '\u0D0E' && LA54_0 <= '\u0D10')||(LA54_0 >= '\u0D12' && LA54_0 <= '\u0D28')||(LA54_0 >= '\u0D2A' && LA54_0 <= '\u0D39')||(LA54_0 >= '\u0D3E' && LA54_0 <= '\u0D43')||(LA54_0 >= '\u0D46' && LA54_0 <= '\u0D48')||(LA54_0 >= '\u0D4A' && LA54_0 <= '\u0D4D')||LA54_0=='\u0D57'||(LA54_0 >= '\u0D60' && LA54_0 <= '\u0D61')||(LA54_0 >= '\u0D66' && LA54_0 <= '\u0D6F')||(LA54_0 >= '\u0D82' && LA54_0 <= '\u0D83')||(LA54_0 >= '\u0D85' && LA54_0 <= '\u0D96')||(LA54_0 >= '\u0D9A' && LA54_0 <= '\u0DB1')||(LA54_0 >= '\u0DB3' && LA54_0 <= '\u0DBB')||LA54_0=='\u0DBD'||(LA54_0 >= '\u0DC0' && LA54_0 <= '\u0DC6')||LA54_0=='\u0DCA'||(LA54_0 >= '\u0DCF' && LA54_0 <= '\u0DD4')||LA54_0=='\u0DD6'||(LA54_0 >= '\u0DD8' && LA54_0 <= '\u0DDF')||(LA54_0 >= '\u0DF2' && LA54_0 <= '\u0DF4')||(LA54_0 >= '\u0E01' && LA54_0 <= '\u0E3A')||(LA54_0 >= '\u0E3F' && LA54_0 <= '\u0E5B')||(LA54_0 >= '\u0E81' && LA54_0 <= '\u0E82')||LA54_0=='\u0E84'||(LA54_0 >= '\u0E87' && LA54_0 <= '\u0E88')||LA54_0=='\u0E8A'||LA54_0=='\u0E8D'||(LA54_0 >= '\u0E94' && LA54_0 <= '\u0E97')||(LA54_0 >= '\u0E99' && LA54_0 <= '\u0E9F')||(LA54_0 >= '\u0EA1' && LA54_0 <= '\u0EA3')||LA54_0=='\u0EA5'||LA54_0=='\u0EA7'||(LA54_0 >= '\u0EAA' && LA54_0 <= '\u0EAB')||(LA54_0 >= '\u0EAD' && LA54_0 <= '\u0EB9')||(LA54_0 >= '\u0EBB' && LA54_0 <= '\u0EBD')||(LA54_0 >= '\u0EC0' && LA54_0 <= '\u0EC4')||LA54_0=='\u0EC6'||(LA54_0 >= '\u0EC8' && LA54_0 <= '\u0ECD')||(LA54_0 >= '\u0ED0' && LA54_0 <= '\u0ED9')||(LA54_0 >= '\u0EDC' && LA54_0 <= '\u0EDD')||(LA54_0 >= '\u0F00' && LA54_0 <= '\u0F39')||(LA54_0 >= '\u0F3E' && LA54_0 <= '\u0F47')||(LA54_0 >= '\u0F49' && LA54_0 <= '\u0F6A')||(LA54_0 >= '\u0F71' && LA54_0 <= '\u0F8B')||(LA54_0 >= '\u0F90' && LA54_0 <= '\u0F97')||(LA54_0 >= '\u0F99' && LA54_0 <= '\u0FBC')||(LA54_0 >= '\u0FBE' && LA54_0 <= '\u0FCC')||LA54_0=='\u0FCF'||(LA54_0 >= '\u1000' && LA54_0 <= '\u1021')||(LA54_0 >= '\u1023' && LA54_0 <= '\u1027')||(LA54_0 >= '\u1029' && LA54_0 <= '\u102A')||(LA54_0 >= '\u102C' && LA54_0 <= '\u1032')||(LA54_0 >= '\u1036' && LA54_0 <= '\u1039')||(LA54_0 >= '\u1040' && LA54_0 <= '\u1059')||(LA54_0 >= '\u10A0' && LA54_0 <= '\u10C5')||(LA54_0 >= '\u10D0' && LA54_0 <= '\u10F8')||LA54_0=='\u10FB'||(LA54_0 >= '\u1100' && LA54_0 <= '\u1159')||(LA54_0 >= '\u115F' && LA54_0 <= '\u11A2')||(LA54_0 >= '\u11A8' && LA54_0 <= '\u11F9')||(LA54_0 >= '\u1200' && LA54_0 <= '\u1206')||(LA54_0 >= '\u1208' && LA54_0 <= '\u1246')||LA54_0=='\u1248'||(LA54_0 >= '\u124A' && LA54_0 <= '\u124D')||(LA54_0 >= '\u1250' && LA54_0 <= '\u1256')||LA54_0=='\u1258'||(LA54_0 >= '\u125A' && LA54_0 <= '\u125D')||(LA54_0 >= '\u1260' && LA54_0 <= '\u1286')||LA54_0=='\u1288'||(LA54_0 >= '\u128A' && LA54_0 <= '\u128D')||(LA54_0 >= '\u1290' && LA54_0 <= '\u12AE')||LA54_0=='\u12B0'||(LA54_0 >= '\u12B2' && LA54_0 <= '\u12B5')||(LA54_0 >= '\u12B8' && LA54_0 <= '\u12BE')||LA54_0=='\u12C0'||(LA54_0 >= '\u12C2' && LA54_0 <= '\u12C5')||(LA54_0 >= '\u12C8' && LA54_0 <= '\u12CE')||(LA54_0 >= '\u12D0' && LA54_0 <= '\u12D6')||(LA54_0 >= '\u12D8' && LA54_0 <= '\u12EE')||(LA54_0 >= '\u12F0' && LA54_0 <= '\u130E')||LA54_0=='\u1310'||(LA54_0 >= '\u1312' && LA54_0 <= '\u1315')||(LA54_0 >= '\u1318' && LA54_0 <= '\u131E')||(LA54_0 >= '\u1320' && LA54_0 <= '\u1346')||(LA54_0 >= '\u1348' && LA54_0 <= '\u135A')||(LA54_0 >= '\u1361' && LA54_0 <= '\u137C')||(LA54_0 >= '\u13A0' && LA54_0 <= '\u13F4')||(LA54_0 >= '\u1401' && LA54_0 <= '\u1676')||(LA54_0 >= '\u1681' && LA54_0 <= '\u169A')||(LA54_0 >= '\u16A0' && LA54_0 <= '\u16F0')||(LA54_0 >= '\u1700' && LA54_0 <= '\u170C')||(LA54_0 >= '\u170E' && LA54_0 <= '\u1714')||(LA54_0 >= '\u1720' && LA54_0 <= '\u1736')||(LA54_0 >= '\u1740' && LA54_0 <= '\u1753')||(LA54_0 >= '\u1760' && LA54_0 <= '\u176C')||(LA54_0 >= '\u176E' && LA54_0 <= '\u1770')||(LA54_0 >= '\u1772' && LA54_0 <= '\u1773')||(LA54_0 >= '\u1780' && LA54_0 <= '\u17B3')||(LA54_0 >= '\u17B6' && LA54_0 <= '\u17DD')||(LA54_0 >= '\u17E0' && LA54_0 <= '\u17E9')||(LA54_0 >= '\u17F0' && LA54_0 <= '\u17F9')||(LA54_0 >= '\u1800' && LA54_0 <= '\u180D')||(LA54_0 >= '\u1810' && LA54_0 <= '\u1819')||(LA54_0 >= '\u1820' && LA54_0 <= '\u1877')||(LA54_0 >= '\u1880' && LA54_0 <= '\u18A9')||(LA54_0 >= '\u1900' && LA54_0 <= '\u191C')||(LA54_0 >= '\u1920' && LA54_0 <= '\u192B')||(LA54_0 >= '\u1930' && LA54_0 <= '\u193B')||LA54_0=='\u1940'||(LA54_0 >= '\u1944' && LA54_0 <= '\u196D')||(LA54_0 >= '\u1970' && LA54_0 <= '\u1974')||(LA54_0 >= '\u19E0' && LA54_0 <= '\u19FF')||(LA54_0 >= '\u1D00' && LA54_0 <= '\u1D6B')||(LA54_0 >= '\u1E00' && LA54_0 <= '\u1E9B')||(LA54_0 >= '\u1EA0' && LA54_0 <= '\u1EF9')||(LA54_0 >= '\u1F00' && LA54_0 <= '\u1F15')||(LA54_0 >= '\u1F18' && LA54_0 <= '\u1F1D')||(LA54_0 >= '\u1F20' && LA54_0 <= '\u1F45')||(LA54_0 >= '\u1F48' && LA54_0 <= '\u1F4D')||(LA54_0 >= '\u1F50' && LA54_0 <= '\u1F57')||LA54_0=='\u1F59'||LA54_0=='\u1F5B'||LA54_0=='\u1F5D'||(LA54_0 >= '\u1F5F' && LA54_0 <= '\u1F7D')||(LA54_0 >= '\u1F80' && LA54_0 <= '\u1FB4')||(LA54_0 >= '\u1FB6' && LA54_0 <= '\u1FBC')||LA54_0=='\u1FBE'||(LA54_0 >= '\u1FC2' && LA54_0 <= '\u1FC4')||(LA54_0 >= '\u1FC6' && LA54_0 <= '\u1FCC')||(LA54_0 >= '\u1FD0' && LA54_0 <= '\u1FD3')||(LA54_0 >= '\u1FD6' && LA54_0 <= '\u1FDB')||(LA54_0 >= '\u1FE0' && LA54_0 <= '\u1FEC')||(LA54_0 >= '\u1FF2' && LA54_0 <= '\u1FF4')||(LA54_0 >= '\u1FF6' && LA54_0 <= '\u1FFC')||(LA54_0 >= '\u2010' && LA54_0 <= '\u2017')||(LA54_0 >= '\u2020' && LA54_0 <= '\u2027')||(LA54_0 >= '\u2030' && LA54_0 <= '\u2038')||(LA54_0 >= '\u203B' && LA54_0 <= '\u2044')||(LA54_0 >= '\u2047' && LA54_0 <= '\u2054')||LA54_0=='\u2057'||(LA54_0 >= '\u2070' && LA54_0 <= '\u2071')||(LA54_0 >= '\u2074' && LA54_0 <= '\u207C')||(LA54_0 >= '\u207F' && LA54_0 <= '\u208C')||(LA54_0 >= '\u20A0' && LA54_0 <= '\u20B1')||(LA54_0 >= '\u20D0' && LA54_0 <= '\u20EA')||(LA54_0 >= '\u2100' && LA54_0 <= '\u213B')||(LA54_0 >= '\u213D' && LA54_0 <= '\u214B')||(LA54_0 >= '\u2153' && LA54_0 <= '\u2183')||(LA54_0 >= '\u2190' && LA54_0 <= '\u2328')||(LA54_0 >= '\u232B' && LA54_0 <= '\u23B3')||(LA54_0 >= '\u23B6' && LA54_0 <= '\u23D0')||(LA54_0 >= '\u2400' && LA54_0 <= '\u2426')||(LA54_0 >= '\u2440' && LA54_0 <= '\u244A')||(LA54_0 >= '\u2460' && LA54_0 <= '\u2617')||(LA54_0 >= '\u2619' && LA54_0 <= '\u267D')||(LA54_0 >= '\u2680' && LA54_0 <= '\u2691')||(LA54_0 >= '\u26A0' && LA54_0 <= '\u26A1')||(LA54_0 >= '\u2701' && LA54_0 <= '\u2704')||(LA54_0 >= '\u2706' && LA54_0 <= '\u2709')||(LA54_0 >= '\u270C' && LA54_0 <= '\u2727')||(LA54_0 >= '\u2729' && LA54_0 <= '\u274B')||LA54_0=='\u274D'||(LA54_0 >= '\u274F' && LA54_0 <= '\u2752')||LA54_0=='\u2756'||(LA54_0 >= '\u2758' && LA54_0 <= '\u275E')||(LA54_0 >= '\u2761' && LA54_0 <= '\u2767')||(LA54_0 >= '\u2776' && LA54_0 <= '\u2794')||(LA54_0 >= '\u2798' && LA54_0 <= '\u27AF')||(LA54_0 >= '\u27B1' && LA54_0 <= '\u27BE')||(LA54_0 >= '\u27D0' && LA54_0 <= '\u27E5')||(LA54_0 >= '\u27F0' && LA54_0 <= '\u2982')||(LA54_0 >= '\u2999' && LA54_0 <= '\u29D7')||(LA54_0 >= '\u29DC' && LA54_0 <= '\u29FB')||(LA54_0 >= '\u29FE' && LA54_0 <= '\u2B0D')||(LA54_0 >= '\u2E80' && LA54_0 <= '\u2E99')||(LA54_0 >= '\u2E9B' && LA54_0 <= '\u2EF3')||(LA54_0 >= '\u2F00' && LA54_0 <= '\u2FD5')||(LA54_0 >= '\u2FF0' && LA54_0 <= '\u2FFB')||(LA54_0 >= '\u3001' && LA54_0 <= '\u3007')||(LA54_0 >= '\u3012' && LA54_0 <= '\u3013')||LA54_0=='\u301C'||(LA54_0 >= '\u3020' && LA54_0 <= '\u303F')||(LA54_0 >= '\u3041' && LA54_0 <= '\u3096')||(LA54_0 >= '\u3099' && LA54_0 <= '\u309A')||(LA54_0 >= '\u309D' && LA54_0 <= '\u30FF')||(LA54_0 >= '\u3105' && LA54_0 <= '\u312C')||(LA54_0 >= '\u3131' && LA54_0 <= '\u318E')||(LA54_0 >= '\u3190' && LA54_0 <= '\u31B7')||(LA54_0 >= '\u31F0' && LA54_0 <= '\u321E')||(LA54_0 >= '\u3220' && LA54_0 <= '\u3243')||(LA54_0 >= '\u3250' && LA54_0 <= '\u327D')||(LA54_0 >= '\u327F' && LA54_0 <= '\u32FE')||(LA54_0 >= '\u3300' && LA54_0 <= '\u4DB5')||(LA54_0 >= '\u4DC0' && LA54_0 <= '\u9FA5')||(LA54_0 >= '\uA000' && LA54_0 <= '\uA48C')||(LA54_0 >= '\uA490' && LA54_0 <= '\uA4C6')||(LA54_0 >= '\uAC00' && LA54_0 <= '\uD7A3')||(LA54_0 >= '\uF900' && LA54_0 <= '\uFA2D')||(LA54_0 >= '\uFA30' && LA54_0 <= '\uFA6A')||(LA54_0 >= '\uFB00' && LA54_0 <= '\uFB06')||(LA54_0 >= '\uFB13' && LA54_0 <= '\uFB17')||(LA54_0 >= '\uFB1D' && LA54_0 <= '\uFB36')||(LA54_0 >= '\uFB38' && LA54_0 <= '\uFB3C')||LA54_0=='\uFB3E'||(LA54_0 >= '\uFB40' && LA54_0 <= '\uFB41')||(LA54_0 >= '\uFB43' && LA54_0 <= '\uFB44')||(LA54_0 >= '\uFB46' && LA54_0 <= '\uFBB1')||(LA54_0 >= '\uFBD3' && LA54_0 <= '\uFD3D')||(LA54_0 >= '\uFD50' && LA54_0 <= '\uFD8F')||(LA54_0 >= '\uFD92' && LA54_0 <= '\uFDC7')||(LA54_0 >= '\uFDF0' && LA54_0 <= '\uFDFD')||(LA54_0 >= '\uFE00' && LA54_0 <= '\uFE0F')||(LA54_0 >= '\uFE20' && LA54_0 <= '\uFE23')||(LA54_0 >= '\uFE30' && LA54_0 <= '\uFE34')||(LA54_0 >= '\uFE45' && LA54_0 <= '\uFE46')||(LA54_0 >= '\uFE49' && LA54_0 <= '\uFE52')||(LA54_0 >= '\uFE54' && LA54_0 <= '\uFE58')||(LA54_0 >= '\uFE5F' && LA54_0 <= '\uFE66')||(LA54_0 >= '\uFE68' && LA54_0 <= '\uFE6B')||(LA54_0 >= '\uFE70' && LA54_0 <= '\uFE74')||(LA54_0 >= '\uFE76' && LA54_0 <= '\uFEFC')||(LA54_0 >= '\uFF01' && LA54_0 <= '\uFF07')||(LA54_0 >= '\uFF0A' && LA54_0 <= '\uFF3A')||LA54_0=='\uFF3C'||LA54_0=='\uFF3F'||(LA54_0 >= '\uFF41' && LA54_0 <= '\uFF5A')||LA54_0=='\uFF5C'||LA54_0=='\uFF5E'||LA54_0=='\uFF61'||(LA54_0 >= '\uFF64' && LA54_0 <= '\uFFBE')||(LA54_0 >= '\uFFC2' && LA54_0 <= '\uFFC7')||(LA54_0 >= '\uFFCA' && LA54_0 <= '\uFFCF')||(LA54_0 >= '\uFFD2' && LA54_0 <= '\uFFD7')||(LA54_0 >= '\uFFDA' && LA54_0 <= '\uFFDC')||(LA54_0 >= '\uFFE0' && LA54_0 <= '\uFFE2')||(LA54_0 >= '\uFFE4' && LA54_0 <= '\uFFE6')||(LA54_0 >= '\uFFE8' && LA54_0 <= '\uFFEE')) ) { + alt54=2; + } + + switch (alt54) { + 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: IN_WORD + { + mIN_WORD(); if (state.failed) return; + + } + break; + + default : + break loop54; + } + } + + } + + 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:1529: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:1530: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:1530: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:1531: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:1532: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:1534: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:1535: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:1536:19: IN_WORD + { + mIN_WORD(); if (state.failed) return; + + } + break; + + default : + break loop56; + } + } + + 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:1542: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:1543: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:1543:9: ( F_ESC | START_WORD | STAR | QUESTION_MARK ) + int alt57=4; + 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 ( (LA57_0=='*') ) { + alt57=3; + } + else if ( (LA57_0=='?') ) { + alt57=4; + } + + 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:1544: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:1545: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:1546: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:1547: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:1549:9: ( F_ESC | IN_WORD | STAR | QUESTION_MARK )* + loop58: + while (true) { + int alt58=5; + 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; + } + else if ( (LA58_0=='*') ) { + alt58=3; + } + else if ( (LA58_0=='?') ) { + alt58=4; + } + + switch (alt58) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1550: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:1551: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:1552: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:1553:19: QUESTION_MARK + { + mQUESTION_MARK(); if (state.failed) return; + + } + break; + + default : + break loop58; + } + } + + } + + 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:1560: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:1561: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:1562:9: ( 'u' F_HEX F_HEX F_HEX F_HEX | . ) + int alt59=2; + int LA59_0 = input.LA(1); + if ( (LA59_0=='u') ) { + int LA59_1 = input.LA(2); + if ( ((LA59_1 >= '0' && LA59_1 <= '9')||(LA59_1 >= 'A' && LA59_1 <= 'F')||(LA59_1 >= 'a' && LA59_1 <= 'f')) ) { + alt59=1; + } + + else { + alt59=2; + } + + } + else if ( ((LA59_0 >= '\u0000' && LA59_0 <= 't')||(LA59_0 >= 'v' && LA59_0 <= '\uFFFF')) ) { + alt59=2; + } + + 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:1564: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:1566: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:1572: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:1580: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:2003: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:2409: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:2410: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:2410:9: ( ' ' | '\\t' | '\\r' | '\\n' | '\\u000C' | '\\u00a0' | '\\u1680' | '\\u180e' | '\\u2000' .. '\\u200b' | '\\u2028' .. '\\u2029' | '\\u202f' | '\\u205f' | '\\u3000' )+ + int cnt60=0; + loop60: + while (true) { + int alt60=2; + int LA60_0 = input.LA(1); + if ( ((LA60_0 >= '\t' && LA60_0 <= '\n')||(LA60_0 >= '\f' && LA60_0 <= '\r')||LA60_0==' '||LA60_0=='\u00A0'||LA60_0=='\u1680'||LA60_0=='\u180E'||(LA60_0 >= '\u2000' && LA60_0 <= '\u200B')||(LA60_0 >= '\u2028' && LA60_0 <= '\u2029')||LA60_0=='\u202F'||LA60_0=='\u205F'||LA60_0=='\u3000') ) { + alt60=1; + } + + switch (alt60) { + 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 ( cnt60 >= 1 ) break loop60; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(60, input); + throw eee; + } + cnt60++; + } + + 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 alt61=36; + alt61 = dfa61.predict(input); + switch (alt61) { + 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 DFA61 dfa61 = new DFA61(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 DFA61_eotS = + "\2\uffff\1\45\1\37\3\41\3\uffff\1\71\1\72\1\uffff\1\73\4\uffff\1\74\3"+ + "\uffff\1\41\2\uffff\1\77\4\uffff\1\41\3\uffff\1\102\3\uffff\1\37\1\102"+ + "\1\uffff\1\102\1\110\1\uffff\10\41\1\uffff\2\117\2\41\4\uffff\2\122\1"+ + "\uffff\2\102\1\uffff\1\37\1\102\1\37\2\102\1\uffff\1\126\1\131\1\126\1"+ + "\131\2\41\1\uffff\2\135\1\uffff\1\102\1\126\1\102\1\uffff\2\102\1\uffff"+ + "\3\41\1\uffff\2\102\1\37\7\102\3\41\16\102\3\41\1\102\1\126\5\102\1\126"+ + "\11\102\3\41\1\102\1\126\3\102\3\126\5\102\1\126\4\102\2\126\1\102\2\126"+ + "\1\102\1\126\3\102\3\126\1\102\7\126\1\102\2\126\1\102\2\126\1\102\5\126"+ + "\2\102\1\126\1\102\2\126\4\102\1\126\1\102\3\126"; + static final String DFA61_eofS = + "\u00d2\uffff"; + static final String DFA61_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\2\41\1\0\2"+ + "\41\1\uffff\10\41\1\0\4\41\4\uffff\2\41\1\uffff\2\41\1\uffff\5\41\1\uffff"+ + "\6\41\1\uffff\2\41\1\uffff\3\41\1\uffff\2\41\1\uffff\3\41\1\uffff\164"+ + "\41"; + static final String DFA61_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\2\uffee\1\uffff\2\uffee\1\uffff\10\uffee\1\uffff"+ + "\4\uffee\4\uffff\2\uffee\1\uffff\2\uffee\1\uffff\5\uffee\1\uffff\6\uffee"+ + "\1\uffff\2\uffee\1\uffff\3\uffee\1\uffff\2\uffee\1\uffff\3\uffee\1\uffff"+ + "\164\uffee"; + static final String DFA61_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\5\uffff\1\43\15"+ + "\uffff\1\12\1\13\1\15\1\22\2\uffff\1\32\2\uffff\1\41\5\uffff\1\42\6\uffff"+ + "\1\4\2\uffff\1\27\3\uffff\1\3\2\uffff\1\6\3\uffff\1\5\164\uffff"; + static final String DFA61_specialS = + "\40\uffff\1\1\7\uffff\1\2\13\uffff\1\0\u009d\uffff}>"; + static final String[] DFA61_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", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\46\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\5\51\1\47\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\47\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\16\57\1\55\13\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\16\56\1\54\13\56\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\21\57\1\66\10\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\21\56\1\65\10\56\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\15\57\1\70\14\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\15\56\1\67\14\56\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "", + "", + "\1\37\1\uffff\12\37", + "\1\37\1\uffff\12\37", + "", + "\7\53\2\uffff\2\53\1\uffff\1\53\1\uffff\13\53\1\uffff\1\53\1\uffff\1"+ + "\53\1\uffff\34\53\1\uffff\1\53\2\uffff\1\53\1\uffff\32\53\1\uffff\1\53"+ + "\44\uffff\7\53\1\uffff\2\53\1\uffff\1\53\1\uffff\1\53\1\uffff\4\53\1"+ + "\uffff\3\53\1\uffff\2\53\1\uffff\u017b\53\31\uffff\162\53\4\uffff\14"+ + "\53\16\uffff\5\53\11\uffff\1\53\21\uffff\130\53\5\uffff\23\53\12\uffff"+ + "\1\53\3\uffff\1\53\7\uffff\5\53\1\uffff\1\53\1\uffff\24\53\1\uffff\54"+ + "\53\1\uffff\54\53\4\uffff\u0087\53\1\uffff\107\53\1\uffff\46\53\2\uffff"+ + "\2\53\6\uffff\20\53\41\uffff\46\53\2\uffff\7\53\1\uffff\47\53\1\uffff"+ + "\2\53\6\uffff\21\53\1\uffff\27\53\1\uffff\12\53\13\uffff\33\53\5\uffff"+ + "\5\53\27\uffff\12\53\5\uffff\1\53\3\uffff\1\53\1\uffff\32\53\5\uffff"+ + "\31\53\7\uffff\175\53\1\uffff\60\53\2\uffff\73\53\2\uffff\3\53\60\uffff"+ + "\62\53\u014f\uffff\71\53\2\uffff\22\53\2\uffff\5\53\3\uffff\31\53\20"+ + "\uffff\3\53\1\uffff\10\53\2\uffff\2\53\2\uffff\26\53\1\uffff\7\53\1\uffff"+ + "\1\53\3\uffff\4\53\2\uffff\11\53\2\uffff\2\53\2\uffff\3\53\11\uffff\1"+ + "\53\4\uffff\2\53\1\uffff\5\53\2\uffff\25\53\6\uffff\3\53\1\uffff\6\53"+ + "\4\uffff\2\53\2\uffff\26\53\1\uffff\7\53\1\uffff\2\53\1\uffff\2\53\1"+ + "\uffff\2\53\2\uffff\1\53\1\uffff\5\53\4\uffff\2\53\2\uffff\3\53\13\uffff"+ + "\4\53\1\uffff\1\53\7\uffff\17\53\14\uffff\3\53\1\uffff\11\53\1\uffff"+ + "\3\53\1\uffff\26\53\1\uffff\7\53\1\uffff\2\53\1\uffff\5\53\2\uffff\12"+ + "\53\1\uffff\3\53\1\uffff\3\53\2\uffff\1\53\17\uffff\4\53\2\uffff\12\53"+ + "\1\uffff\1\53\17\uffff\3\53\1\uffff\10\53\2\uffff\2\53\2\uffff\26\53"+ + "\1\uffff\7\53\1\uffff\2\53\1\uffff\5\53\2\uffff\10\53\3\uffff\2\53\2"+ + "\uffff\3\53\10\uffff\2\53\4\uffff\2\53\1\uffff\3\53\4\uffff\14\53\20"+ + "\uffff\2\53\1\uffff\6\53\3\uffff\3\53\1\uffff\4\53\3\uffff\2\53\1\uffff"+ + "\1\53\1\uffff\2\53\3\uffff\2\53\3\uffff\3\53\3\uffff\10\53\1\uffff\3"+ + "\53\4\uffff\5\53\3\uffff\3\53\1\uffff\4\53\11\uffff\1\53\17\uffff\24"+ + "\53\6\uffff\3\53\1\uffff\10\53\1\uffff\3\53\1\uffff\27\53\1\uffff\12"+ + "\53\1\uffff\5\53\4\uffff\7\53\1\uffff\3\53\1\uffff\4\53\7\uffff\2\53"+ + "\11\uffff\2\53\4\uffff\12\53\22\uffff\2\53\1\uffff\10\53\1\uffff\3\53"+ + "\1\uffff\27\53\1\uffff\12\53\1\uffff\5\53\2\uffff\11\53\1\uffff\3\53"+ + "\1\uffff\4\53\7\uffff\2\53\7\uffff\1\53\1\uffff\2\53\4\uffff\12\53\22"+ + "\uffff\2\53\1\uffff\10\53\1\uffff\3\53\1\uffff\27\53\1\uffff\20\53\4"+ + "\uffff\6\53\2\uffff\3\53\1\uffff\4\53\11\uffff\1\53\10\uffff\2\53\4\uffff"+ + "\12\53\22\uffff\2\53\1\uffff\22\53\3\uffff\30\53\1\uffff\11\53\1\uffff"+ + "\1\53\2\uffff\7\53\3\uffff\1\53\4\uffff\6\53\1\uffff\1\53\1\uffff\10"+ + "\53\22\uffff\3\53\14\uffff\72\53\4\uffff\35\53\45\uffff\2\53\1\uffff"+ + "\1\53\2\uffff\2\53\1\uffff\1\53\2\uffff\1\53\6\uffff\4\53\1\uffff\7\53"+ + "\1\uffff\3\53\1\uffff\1\53\1\uffff\1\53\2\uffff\2\53\1\uffff\15\53\1"+ + "\uffff\3\53\2\uffff\5\53\1\uffff\1\53\1\uffff\6\53\2\uffff\12\53\2\uffff"+ + "\2\53\42\uffff\72\53\4\uffff\12\53\1\uffff\42\53\6\uffff\33\53\4\uffff"+ + "\10\53\1\uffff\44\53\1\uffff\17\53\2\uffff\1\53\60\uffff\42\53\1\uffff"+ + "\5\53\1\uffff\2\53\1\uffff\7\53\3\uffff\4\53\6\uffff\32\53\106\uffff"+ + "\46\53\12\uffff\51\53\2\uffff\1\53\4\uffff\132\53\5\uffff\104\53\5\uffff"+ + "\122\53\6\uffff\7\53\1\uffff\77\53\1\uffff\1\53\1\uffff\4\53\2\uffff"+ + "\7\53\1\uffff\1\53\1\uffff\4\53\2\uffff\47\53\1\uffff\1\53\1\uffff\4"+ + "\53\2\uffff\37\53\1\uffff\1\53\1\uffff\4\53\2\uffff\7\53\1\uffff\1\53"+ + "\1\uffff\4\53\2\uffff\7\53\1\uffff\7\53\1\uffff\27\53\1\uffff\37\53\1"+ + "\uffff\1\53\1\uffff\4\53\2\uffff\7\53\1\uffff\47\53\1\uffff\23\53\6\uffff"+ + "\34\53\43\uffff\125\53\14\uffff\u0276\53\12\uffff\32\53\5\uffff\121\53"+ + "\17\uffff\15\53\1\uffff\7\53\13\uffff\27\53\11\uffff\24\53\14\uffff\15"+ + "\53\1\uffff\3\53\1\uffff\2\53\14\uffff\64\53\2\uffff\50\53\2\uffff\12"+ + "\53\6\uffff\12\53\6\uffff\16\53\2\uffff\12\53\6\uffff\130\53\10\uffff"+ + "\52\53\126\uffff\35\53\3\uffff\14\53\4\uffff\14\53\4\uffff\1\53\3\uffff"+ + "\52\53\2\uffff\5\53\153\uffff\40\53\u0300\uffff\154\53\u0094\uffff\u009c"+ + "\53\4\uffff\132\53\6\uffff\26\53\2\uffff\6\53\2\uffff\46\53\2\uffff\6"+ + "\53\2\uffff\10\53\1\uffff\1\53\1\uffff\1\53\1\uffff\1\53\1\uffff\37\53"+ + "\2\uffff\65\53\1\uffff\7\53\1\uffff\1\53\3\uffff\3\53\1\uffff\7\53\3"+ + "\uffff\4\53\2\uffff\6\53\4\uffff\15\53\5\uffff\3\53\1\uffff\7\53\23\uffff"+ + "\10\53\10\uffff\10\53\10\uffff\11\53\2\uffff\12\53\2\uffff\16\53\2\uffff"+ + "\1\53\30\uffff\2\53\2\uffff\11\53\2\uffff\16\53\23\uffff\22\53\36\uffff"+ + "\33\53\25\uffff\74\53\1\uffff\17\53\7\uffff\61\53\14\uffff\u0199\53\2"+ + "\uffff\u0089\53\2\uffff\33\53\57\uffff\47\53\31\uffff\13\53\25\uffff"+ + "\u01b8\53\1\uffff\145\53\2\uffff\22\53\16\uffff\2\53\137\uffff\4\53\1"+ + "\uffff\4\53\2\uffff\34\53\1\uffff\43\53\1\uffff\1\53\1\uffff\4\53\3\uffff"+ + "\1\53\1\uffff\7\53\2\uffff\7\53\16\uffff\37\53\3\uffff\30\53\1\uffff"+ + "\16\53\21\uffff\26\53\12\uffff\u0193\53\26\uffff\77\53\4\uffff\40\53"+ + "\2\uffff\u0110\53\u0372\uffff\32\53\1\uffff\131\53\14\uffff\u00d6\53"+ + "\32\uffff\14\53\5\uffff\7\53\12\uffff\2\53\10\uffff\1\53\3\uffff\40\53"+ + "\1\uffff\126\53\2\uffff\2\53\2\uffff\143\53\5\uffff\50\53\4\uffff\136"+ + "\53\1\uffff\50\53\70\uffff\57\53\1\uffff\44\53\14\uffff\56\53\1\uffff"+ + "\u0080\53\1\uffff\u1ab6\53\12\uffff\u51e6\53\132\uffff\u048d\53\3\uffff"+ + "\67\53\u0739\uffff\u2ba4\53\u215c\uffff\u012e\53\2\uffff\73\53\u0095"+ + "\uffff\7\53\14\uffff\5\53\5\uffff\32\53\1\uffff\5\53\1\uffff\1\53\1\uffff"+ + "\2\53\1\uffff\2\53\1\uffff\154\53\41\uffff\u016b\53\22\uffff\100\53\2"+ + "\uffff\66\53\50\uffff\16\53\2\uffff\20\53\20\uffff\4\53\14\uffff\5\53"+ + "\20\uffff\2\53\2\uffff\12\53\1\uffff\5\53\6\uffff\10\53\1\uffff\4\53"+ + "\4\uffff\5\53\1\uffff\u0087\53\4\uffff\7\53\2\uffff\61\53\1\uffff\1\53"+ + "\2\uffff\1\53\1\uffff\32\53\1\uffff\1\53\1\uffff\1\53\2\uffff\1\53\2"+ + "\uffff\133\53\3\uffff\6\53\2\uffff\6\53\2\uffff\6\53\2\uffff\3\53\3\uffff"+ + "\3\53\1\uffff\3\53\1\uffff\7\53", + "", + "", + "", + "", + "\7\53\2\uffff\2\53\1\uffff\1\53\1\uffff\13\53\1\uffff\1\53\1\uffff\1"+ + "\53\1\uffff\34\53\1\uffff\1\53\2\uffff\1\53\1\uffff\32\53\1\uffff\1\53"+ + "\44\uffff\7\53\1\uffff\2\53\1\uffff\1\53\1\uffff\1\53\1\uffff\4\53\1"+ + "\uffff\3\53\1\uffff\2\53\1\uffff\u017b\53\31\uffff\162\53\4\uffff\14"+ + "\53\16\uffff\5\53\11\uffff\1\53\21\uffff\130\53\5\uffff\23\53\12\uffff"+ + "\1\53\3\uffff\1\53\7\uffff\5\53\1\uffff\1\53\1\uffff\24\53\1\uffff\54"+ + "\53\1\uffff\54\53\4\uffff\u0087\53\1\uffff\107\53\1\uffff\46\53\2\uffff"+ + "\2\53\6\uffff\20\53\41\uffff\46\53\2\uffff\7\53\1\uffff\47\53\1\uffff"+ + "\2\53\6\uffff\21\53\1\uffff\27\53\1\uffff\12\53\13\uffff\33\53\5\uffff"+ + "\5\53\27\uffff\12\53\5\uffff\1\53\3\uffff\1\53\1\uffff\32\53\5\uffff"+ + "\31\53\7\uffff\175\53\1\uffff\60\53\2\uffff\73\53\2\uffff\3\53\60\uffff"+ + "\62\53\u014f\uffff\71\53\2\uffff\22\53\2\uffff\5\53\3\uffff\31\53\20"+ + "\uffff\3\53\1\uffff\10\53\2\uffff\2\53\2\uffff\26\53\1\uffff\7\53\1\uffff"+ + "\1\53\3\uffff\4\53\2\uffff\11\53\2\uffff\2\53\2\uffff\3\53\11\uffff\1"+ + "\53\4\uffff\2\53\1\uffff\5\53\2\uffff\25\53\6\uffff\3\53\1\uffff\6\53"+ + "\4\uffff\2\53\2\uffff\26\53\1\uffff\7\53\1\uffff\2\53\1\uffff\2\53\1"+ + "\uffff\2\53\2\uffff\1\53\1\uffff\5\53\4\uffff\2\53\2\uffff\3\53\13\uffff"+ + "\4\53\1\uffff\1\53\7\uffff\17\53\14\uffff\3\53\1\uffff\11\53\1\uffff"+ + "\3\53\1\uffff\26\53\1\uffff\7\53\1\uffff\2\53\1\uffff\5\53\2\uffff\12"+ + "\53\1\uffff\3\53\1\uffff\3\53\2\uffff\1\53\17\uffff\4\53\2\uffff\12\53"+ + "\1\uffff\1\53\17\uffff\3\53\1\uffff\10\53\2\uffff\2\53\2\uffff\26\53"+ + "\1\uffff\7\53\1\uffff\2\53\1\uffff\5\53\2\uffff\10\53\3\uffff\2\53\2"+ + "\uffff\3\53\10\uffff\2\53\4\uffff\2\53\1\uffff\3\53\4\uffff\14\53\20"+ + "\uffff\2\53\1\uffff\6\53\3\uffff\3\53\1\uffff\4\53\3\uffff\2\53\1\uffff"+ + "\1\53\1\uffff\2\53\3\uffff\2\53\3\uffff\3\53\3\uffff\10\53\1\uffff\3"+ + "\53\4\uffff\5\53\3\uffff\3\53\1\uffff\4\53\11\uffff\1\53\17\uffff\24"+ + "\53\6\uffff\3\53\1\uffff\10\53\1\uffff\3\53\1\uffff\27\53\1\uffff\12"+ + "\53\1\uffff\5\53\4\uffff\7\53\1\uffff\3\53\1\uffff\4\53\7\uffff\2\53"+ + "\11\uffff\2\53\4\uffff\12\53\22\uffff\2\53\1\uffff\10\53\1\uffff\3\53"+ + "\1\uffff\27\53\1\uffff\12\53\1\uffff\5\53\2\uffff\11\53\1\uffff\3\53"+ + "\1\uffff\4\53\7\uffff\2\53\7\uffff\1\53\1\uffff\2\53\4\uffff\12\53\22"+ + "\uffff\2\53\1\uffff\10\53\1\uffff\3\53\1\uffff\27\53\1\uffff\20\53\4"+ + "\uffff\6\53\2\uffff\3\53\1\uffff\4\53\11\uffff\1\53\10\uffff\2\53\4\uffff"+ + "\12\53\22\uffff\2\53\1\uffff\22\53\3\uffff\30\53\1\uffff\11\53\1\uffff"+ + "\1\53\2\uffff\7\53\3\uffff\1\53\4\uffff\6\53\1\uffff\1\53\1\uffff\10"+ + "\53\22\uffff\3\53\14\uffff\72\53\4\uffff\35\53\45\uffff\2\53\1\uffff"+ + "\1\53\2\uffff\2\53\1\uffff\1\53\2\uffff\1\53\6\uffff\4\53\1\uffff\7\53"+ + "\1\uffff\3\53\1\uffff\1\53\1\uffff\1\53\2\uffff\2\53\1\uffff\15\53\1"+ + "\uffff\3\53\2\uffff\5\53\1\uffff\1\53\1\uffff\6\53\2\uffff\12\53\2\uffff"+ + "\2\53\42\uffff\72\53\4\uffff\12\53\1\uffff\42\53\6\uffff\33\53\4\uffff"+ + "\10\53\1\uffff\44\53\1\uffff\17\53\2\uffff\1\53\60\uffff\42\53\1\uffff"+ + "\5\53\1\uffff\2\53\1\uffff\7\53\3\uffff\4\53\6\uffff\32\53\106\uffff"+ + "\46\53\12\uffff\51\53\2\uffff\1\53\4\uffff\132\53\5\uffff\104\53\5\uffff"+ + "\122\53\6\uffff\7\53\1\uffff\77\53\1\uffff\1\53\1\uffff\4\53\2\uffff"+ + "\7\53\1\uffff\1\53\1\uffff\4\53\2\uffff\47\53\1\uffff\1\53\1\uffff\4"+ + "\53\2\uffff\37\53\1\uffff\1\53\1\uffff\4\53\2\uffff\7\53\1\uffff\1\53"+ + "\1\uffff\4\53\2\uffff\7\53\1\uffff\7\53\1\uffff\27\53\1\uffff\37\53\1"+ + "\uffff\1\53\1\uffff\4\53\2\uffff\7\53\1\uffff\47\53\1\uffff\23\53\6\uffff"+ + "\34\53\43\uffff\125\53\14\uffff\u0276\53\12\uffff\32\53\5\uffff\121\53"+ + "\17\uffff\15\53\1\uffff\7\53\13\uffff\27\53\11\uffff\24\53\14\uffff\15"+ + "\53\1\uffff\3\53\1\uffff\2\53\14\uffff\64\53\2\uffff\50\53\2\uffff\12"+ + "\53\6\uffff\12\53\6\uffff\16\53\2\uffff\12\53\6\uffff\130\53\10\uffff"+ + "\52\53\126\uffff\35\53\3\uffff\14\53\4\uffff\14\53\4\uffff\1\53\3\uffff"+ + "\52\53\2\uffff\5\53\153\uffff\40\53\u0300\uffff\154\53\u0094\uffff\u009c"+ + "\53\4\uffff\132\53\6\uffff\26\53\2\uffff\6\53\2\uffff\46\53\2\uffff\6"+ + "\53\2\uffff\10\53\1\uffff\1\53\1\uffff\1\53\1\uffff\1\53\1\uffff\37\53"+ + "\2\uffff\65\53\1\uffff\7\53\1\uffff\1\53\3\uffff\3\53\1\uffff\7\53\3"+ + "\uffff\4\53\2\uffff\6\53\4\uffff\15\53\5\uffff\3\53\1\uffff\7\53\23\uffff"+ + "\10\53\10\uffff\10\53\10\uffff\11\53\2\uffff\12\53\2\uffff\16\53\2\uffff"+ + "\1\53\30\uffff\2\53\2\uffff\11\53\2\uffff\16\53\23\uffff\22\53\36\uffff"+ + "\33\53\25\uffff\74\53\1\uffff\17\53\7\uffff\61\53\14\uffff\u0199\53\2"+ + "\uffff\u0089\53\2\uffff\33\53\57\uffff\47\53\31\uffff\13\53\25\uffff"+ + "\u01b8\53\1\uffff\145\53\2\uffff\22\53\16\uffff\2\53\137\uffff\4\53\1"+ + "\uffff\4\53\2\uffff\34\53\1\uffff\43\53\1\uffff\1\53\1\uffff\4\53\3\uffff"+ + "\1\53\1\uffff\7\53\2\uffff\7\53\16\uffff\37\53\3\uffff\30\53\1\uffff"+ + "\16\53\21\uffff\26\53\12\uffff\u0193\53\26\uffff\77\53\4\uffff\40\53"+ + "\2\uffff\u0110\53\u0372\uffff\32\53\1\uffff\131\53\14\uffff\u00d6\53"+ + "\32\uffff\14\53\5\uffff\7\53\12\uffff\2\53\10\uffff\1\53\3\uffff\40\53"+ + "\1\uffff\126\53\2\uffff\2\53\2\uffff\143\53\5\uffff\50\53\4\uffff\136"+ + "\53\1\uffff\50\53\70\uffff\57\53\1\uffff\44\53\14\uffff\56\53\1\uffff"+ + "\u0080\53\1\uffff\u1ab6\53\12\uffff\u51e6\53\132\uffff\u048d\53\3\uffff"+ + "\67\53\u0739\uffff\u2ba4\53\u215c\uffff\u012e\53\2\uffff\73\53\u0095"+ + "\uffff\7\53\14\uffff\5\53\5\uffff\32\53\1\uffff\5\53\1\uffff\1\53\1\uffff"+ + "\2\53\1\uffff\2\53\1\uffff\154\53\41\uffff\u016b\53\22\uffff\100\53\2"+ + "\uffff\66\53\50\uffff\16\53\2\uffff\20\53\20\uffff\4\53\14\uffff\5\53"+ + "\20\uffff\2\53\2\uffff\12\53\1\uffff\5\53\6\uffff\10\53\1\uffff\4\53"+ + "\4\uffff\5\53\1\uffff\u0087\53\4\uffff\7\53\2\uffff\61\53\1\uffff\1\53"+ + "\2\uffff\1\53\1\uffff\32\53\1\uffff\1\53\1\uffff\1\53\2\uffff\1\53\2"+ + "\uffff\133\53\3\uffff\6\53\2\uffff\6\53\2\uffff\6\53\2\uffff\3\53\3\uffff"+ + "\3\53\1\uffff\3\53\1\uffff\7\53", + "", + "", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\16\57\1\76\13\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\16\56\1\75\13\56\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "", + "", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\165\101\1\100\uff8a\101", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\103\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\5\51\1\47\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\47\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\104\1\uffff\1\104\1\uffff\1\51\12\105\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\32\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\165\107\1\106\uff8a\107", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\53\2\uffff\2\53\1\uffff\1\53\1\uffff\13\53\1\uffff\1\53\1\uffff\1"+ + "\53\1\uffff\34\53\1\uffff\1\53\2\uffff\1\53\1\uffff\32\53\1\uffff\1\53"+ + "\44\uffff\7\53\1\uffff\2\53\1\uffff\1\53\1\uffff\1\53\1\uffff\4\53\1"+ + "\uffff\3\53\1\uffff\2\53\1\uffff\u017b\53\31\uffff\162\53\4\uffff\14"+ + "\53\16\uffff\5\53\11\uffff\1\53\21\uffff\130\53\5\uffff\23\53\12\uffff"+ + "\1\53\3\uffff\1\53\7\uffff\5\53\1\uffff\1\53\1\uffff\24\53\1\uffff\54"+ + "\53\1\uffff\54\53\4\uffff\u0087\53\1\uffff\107\53\1\uffff\46\53\2\uffff"+ + "\2\53\6\uffff\20\53\41\uffff\46\53\2\uffff\7\53\1\uffff\47\53\1\uffff"+ + "\2\53\6\uffff\21\53\1\uffff\27\53\1\uffff\12\53\13\uffff\33\53\5\uffff"+ + "\5\53\27\uffff\12\53\5\uffff\1\53\3\uffff\1\53\1\uffff\32\53\5\uffff"+ + "\31\53\7\uffff\175\53\1\uffff\60\53\2\uffff\73\53\2\uffff\3\53\60\uffff"+ + "\62\53\u014f\uffff\71\53\2\uffff\22\53\2\uffff\5\53\3\uffff\31\53\20"+ + "\uffff\3\53\1\uffff\10\53\2\uffff\2\53\2\uffff\26\53\1\uffff\7\53\1\uffff"+ + "\1\53\3\uffff\4\53\2\uffff\11\53\2\uffff\2\53\2\uffff\3\53\11\uffff\1"+ + "\53\4\uffff\2\53\1\uffff\5\53\2\uffff\25\53\6\uffff\3\53\1\uffff\6\53"+ + "\4\uffff\2\53\2\uffff\26\53\1\uffff\7\53\1\uffff\2\53\1\uffff\2\53\1"+ + "\uffff\2\53\2\uffff\1\53\1\uffff\5\53\4\uffff\2\53\2\uffff\3\53\13\uffff"+ + "\4\53\1\uffff\1\53\7\uffff\17\53\14\uffff\3\53\1\uffff\11\53\1\uffff"+ + "\3\53\1\uffff\26\53\1\uffff\7\53\1\uffff\2\53\1\uffff\5\53\2\uffff\12"+ + "\53\1\uffff\3\53\1\uffff\3\53\2\uffff\1\53\17\uffff\4\53\2\uffff\12\53"+ + "\1\uffff\1\53\17\uffff\3\53\1\uffff\10\53\2\uffff\2\53\2\uffff\26\53"+ + "\1\uffff\7\53\1\uffff\2\53\1\uffff\5\53\2\uffff\10\53\3\uffff\2\53\2"+ + "\uffff\3\53\10\uffff\2\53\4\uffff\2\53\1\uffff\3\53\4\uffff\14\53\20"+ + "\uffff\2\53\1\uffff\6\53\3\uffff\3\53\1\uffff\4\53\3\uffff\2\53\1\uffff"+ + "\1\53\1\uffff\2\53\3\uffff\2\53\3\uffff\3\53\3\uffff\10\53\1\uffff\3"+ + "\53\4\uffff\5\53\3\uffff\3\53\1\uffff\4\53\11\uffff\1\53\17\uffff\24"+ + "\53\6\uffff\3\53\1\uffff\10\53\1\uffff\3\53\1\uffff\27\53\1\uffff\12"+ + "\53\1\uffff\5\53\4\uffff\7\53\1\uffff\3\53\1\uffff\4\53\7\uffff\2\53"+ + "\11\uffff\2\53\4\uffff\12\53\22\uffff\2\53\1\uffff\10\53\1\uffff\3\53"+ + "\1\uffff\27\53\1\uffff\12\53\1\uffff\5\53\2\uffff\11\53\1\uffff\3\53"+ + "\1\uffff\4\53\7\uffff\2\53\7\uffff\1\53\1\uffff\2\53\4\uffff\12\53\22"+ + "\uffff\2\53\1\uffff\10\53\1\uffff\3\53\1\uffff\27\53\1\uffff\20\53\4"+ + "\uffff\6\53\2\uffff\3\53\1\uffff\4\53\11\uffff\1\53\10\uffff\2\53\4\uffff"+ + "\12\53\22\uffff\2\53\1\uffff\22\53\3\uffff\30\53\1\uffff\11\53\1\uffff"+ + "\1\53\2\uffff\7\53\3\uffff\1\53\4\uffff\6\53\1\uffff\1\53\1\uffff\10"+ + "\53\22\uffff\3\53\14\uffff\72\53\4\uffff\35\53\45\uffff\2\53\1\uffff"+ + "\1\53\2\uffff\2\53\1\uffff\1\53\2\uffff\1\53\6\uffff\4\53\1\uffff\7\53"+ + "\1\uffff\3\53\1\uffff\1\53\1\uffff\1\53\2\uffff\2\53\1\uffff\15\53\1"+ + "\uffff\3\53\2\uffff\5\53\1\uffff\1\53\1\uffff\6\53\2\uffff\12\53\2\uffff"+ + "\2\53\42\uffff\72\53\4\uffff\12\53\1\uffff\42\53\6\uffff\33\53\4\uffff"+ + "\10\53\1\uffff\44\53\1\uffff\17\53\2\uffff\1\53\60\uffff\42\53\1\uffff"+ + "\5\53\1\uffff\2\53\1\uffff\7\53\3\uffff\4\53\6\uffff\32\53\106\uffff"+ + "\46\53\12\uffff\51\53\2\uffff\1\53\4\uffff\132\53\5\uffff\104\53\5\uffff"+ + "\122\53\6\uffff\7\53\1\uffff\77\53\1\uffff\1\53\1\uffff\4\53\2\uffff"+ + "\7\53\1\uffff\1\53\1\uffff\4\53\2\uffff\47\53\1\uffff\1\53\1\uffff\4"+ + "\53\2\uffff\37\53\1\uffff\1\53\1\uffff\4\53\2\uffff\7\53\1\uffff\1\53"+ + "\1\uffff\4\53\2\uffff\7\53\1\uffff\7\53\1\uffff\27\53\1\uffff\37\53\1"+ + "\uffff\1\53\1\uffff\4\53\2\uffff\7\53\1\uffff\47\53\1\uffff\23\53\6\uffff"+ + "\34\53\43\uffff\125\53\14\uffff\u0276\53\12\uffff\32\53\5\uffff\121\53"+ + "\17\uffff\15\53\1\uffff\7\53\13\uffff\27\53\11\uffff\24\53\14\uffff\15"+ + "\53\1\uffff\3\53\1\uffff\2\53\14\uffff\64\53\2\uffff\50\53\2\uffff\12"+ + "\53\6\uffff\12\53\6\uffff\16\53\2\uffff\12\53\6\uffff\130\53\10\uffff"+ + "\52\53\126\uffff\35\53\3\uffff\14\53\4\uffff\14\53\4\uffff\1\53\3\uffff"+ + "\52\53\2\uffff\5\53\153\uffff\40\53\u0300\uffff\154\53\u0094\uffff\u009c"+ + "\53\4\uffff\132\53\6\uffff\26\53\2\uffff\6\53\2\uffff\46\53\2\uffff\6"+ + "\53\2\uffff\10\53\1\uffff\1\53\1\uffff\1\53\1\uffff\1\53\1\uffff\37\53"+ + "\2\uffff\65\53\1\uffff\7\53\1\uffff\1\53\3\uffff\3\53\1\uffff\7\53\3"+ + "\uffff\4\53\2\uffff\6\53\4\uffff\15\53\5\uffff\3\53\1\uffff\7\53\23\uffff"+ + "\10\53\10\uffff\10\53\10\uffff\11\53\2\uffff\12\53\2\uffff\16\53\2\uffff"+ + "\1\53\30\uffff\2\53\2\uffff\11\53\2\uffff\16\53\23\uffff\22\53\36\uffff"+ + "\33\53\25\uffff\74\53\1\uffff\17\53\7\uffff\61\53\14\uffff\u0199\53\2"+ + "\uffff\u0089\53\2\uffff\33\53\57\uffff\47\53\31\uffff\13\53\25\uffff"+ + "\u01b8\53\1\uffff\145\53\2\uffff\22\53\16\uffff\2\53\137\uffff\4\53\1"+ + "\uffff\4\53\2\uffff\34\53\1\uffff\43\53\1\uffff\1\53\1\uffff\4\53\3\uffff"+ + "\1\53\1\uffff\7\53\2\uffff\7\53\16\uffff\37\53\3\uffff\30\53\1\uffff"+ + "\16\53\21\uffff\26\53\12\uffff\u0193\53\26\uffff\77\53\4\uffff\40\53"+ + "\2\uffff\u0110\53\u0372\uffff\32\53\1\uffff\131\53\14\uffff\u00d6\53"+ + "\32\uffff\14\53\5\uffff\7\53\12\uffff\2\53\10\uffff\1\53\3\uffff\40\53"+ + "\1\uffff\126\53\2\uffff\2\53\2\uffff\143\53\5\uffff\50\53\4\uffff\136"+ + "\53\1\uffff\50\53\70\uffff\57\53\1\uffff\44\53\14\uffff\56\53\1\uffff"+ + "\u0080\53\1\uffff\u1ab6\53\12\uffff\u51e6\53\132\uffff\u048d\53\3\uffff"+ + "\67\53\u0739\uffff\u2ba4\53\u215c\uffff\u012e\53\2\uffff\73\53\u0095"+ + "\uffff\7\53\14\uffff\5\53\5\uffff\32\53\1\uffff\5\53\1\uffff\1\53\1\uffff"+ + "\2\53\1\uffff\2\53\1\uffff\154\53\41\uffff\u016b\53\22\uffff\100\53\2"+ + "\uffff\66\53\50\uffff\16\53\2\uffff\20\53\20\uffff\4\53\14\uffff\5\53"+ + "\20\uffff\2\53\2\uffff\12\53\1\uffff\5\53\6\uffff\10\53\1\uffff\4\53"+ + "\4\uffff\5\53\1\uffff\u0087\53\4\uffff\7\53\2\uffff\61\53\1\uffff\1\53"+ + "\2\uffff\1\53\1\uffff\32\53\1\uffff\1\53\1\uffff\1\53\2\uffff\1\53\2"+ + "\uffff\133\53\3\uffff\6\53\2\uffff\6\53\2\uffff\6\53\2\uffff\3\53\3\uffff"+ + "\3\53\1\uffff\3\53\1\uffff\7\53", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\23\57\1\114\2\57\1\113"+ + "\3\57\1\uffff\1\64\2\uffff\1\61\1\uffff\23\56\1\112\2\56\1\111\3\56\1"+ + "\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff"+ + "\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\23\57\1\114\2\57\1\113"+ + "\3\57\1\uffff\1\64\2\uffff\1\61\1\uffff\23\56\1\112\2\56\1\111\3\56\1"+ + "\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff"+ + "\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\165\116\1\115\uff8a\116", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\3\57\1\121\26\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\3\56\1\120\26\56\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\3\57\1\121\26\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\3\56\1\120\26\56\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "", + "", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\123\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\123\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\123\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\124\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\5\51\1\47\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\47\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\105\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32"+ + "\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51"+ + "\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162"+ + "\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\105\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32"+ + "\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51"+ + "\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162"+ + "\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\125\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\125\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\125\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\1\127"+ + "\12\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64"+ + "\2\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\1\127"+ + "\12\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64"+ + "\2\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\134\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\133\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\132\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\136\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\136\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\136\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\137\1\37\1\127\12\140\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\5\51\1\47\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\47\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\141\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\141\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\141\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\4\51\1\144\3\51\1\145\4\51\1\143\5\51\1\146\5\51\1"+ + "\142\1\51\1\uffff\1\50\2\uffff\1\51\1\uffff\3\51\1\144\3\51\1\145\4\51"+ + "\1\143\5\51\1\146\5\51\1\142\1\51\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\147\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32"+ + "\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51"+ + "\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162"+ + "\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\152\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\151\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\150\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\152\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\151\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\150\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\152\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\151\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\150\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\153\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\153\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\153\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\154\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32"+ + "\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51"+ + "\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162"+ + "\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\140\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\5\51\1\47\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\47\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\155\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\155\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\155\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\156\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\156\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51"+ + "\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130"+ + "\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51"+ + "\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107"+ + "\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12"+ + "\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1"+ + "\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\11\51\1\160\5\51\1\157\13\51\1\uffff\1\50\2\uffff"+ + "\1\51\1\uffff\10\51\1\160\5\51\1\157\13\51\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\1\51\1\161\31\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\1\161\31\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\17\51\1\162\13\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\16\51\1\162\13\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\163\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\163\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51"+ + "\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130"+ + "\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51"+ + "\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107"+ + "\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12"+ + "\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1"+ + "\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\147\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\4\51\1\166\3\51\1\167\4\51\1\165\5\51\1\170"+ + "\5\51\1\164\1\51\1\uffff\1\50\2\uffff\1\51\1\uffff\3\51\1\166\3\51\1"+ + "\167\4\51\1\165\5\51\1\170\5\51\1\164\1\51\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\173\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\172\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\171\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\173\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\172\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\171\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\173\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\172\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\171\24\56\1\uffff\1\51\44\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51"+ + "\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff"+ + "\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff"+ + "\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff"+ + "\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41"+ + "\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1"+ + "\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51"+ + "\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51"+ + "\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff"+ + "\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff"+ + "\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4"+ + "\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51"+ + "\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff"+ + "\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1"+ + "\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26"+ + "\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51"+ + "\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2"+ + "\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51"+ + "\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff"+ + "\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3"+ + "\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1"+ + "\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff"+ + "\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4"+ + "\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22"+ + "\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51"+ + "\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51"+ + "\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2"+ + "\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1"+ + "\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12"+ + "\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17"+ + "\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51"+ + "\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1"+ + "\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff"+ + "\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\174\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\174\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\174\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\175\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\4\51\1\166\3\51\1\167\4\51\1\165\5\51\1\170"+ + "\5\51\1\164\1\51\1\uffff\1\50\2\uffff\1\51\1\uffff\3\51\1\166\3\51\1"+ + "\167\4\51\1\165\5\51\1\170\5\51\1\164\1\51\1\uffff\1\51\44\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\176\1\uffff\1\51"+ + "\1\uffff\1\51\1\uffff\1\53\1\51\6\176\24\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\6\176\24\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\1\51\1\177\31\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\1\177\31\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\16\51\1\u0080\14\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\15\51\1\u0080\14\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\14\51\1\u0082\1\51\1\u0081\14\51\1\uffff\1\50\2\uffff"+ + "\1\51\1\uffff\13\51\1\u0082\1\51\1\u0081\14\51\1\uffff\1\51\44\uffff"+ + "\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\24\51\1\u0084\4\51\1\u0083\1\51\1\uffff\1\50\2\uffff"+ + "\1\51\1\uffff\23\51\1\u0084\4\51\1\u0083\1\51\1\uffff\1\51\44\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\25\51\1\u0085\5\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\24\51\1\u0085\5\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\3\51\1\u0086\27\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\2\51\1\u0086\27\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\u0087\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\u0087\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\11\51\1\u0089\5\51\1\u0088\13\51\1\uffff\1\50\2\uffff"+ + "\1\51\1\uffff\10\51\1\u0089\5\51\1\u0088\13\51\1\uffff\1\51\44\uffff"+ + "\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\1\51\1\u008a\31\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\1\u008a\31\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31"+ + "\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130"+ + "\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51"+ + "\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107"+ + "\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12"+ + "\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1"+ + "\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\17\51\1\u008b\13\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\16\51\1\u008b\13\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\u008c\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\u008c\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\u008f\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\u008e\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\u008d\24\56\1\uffff\1\51\44\uffff\7\51\1"+ + "\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\u008f\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\u008e\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\u008d\24\56\1\uffff\1\51\44\uffff\7\51\1"+ + "\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\u008f\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\6\u008e\24\57\1\uffff"+ + "\1\64\2\uffff\1\61\1\uffff\6\u008d\24\56\1\uffff\1\51\44\uffff\7\51\1"+ + "\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff"+ + "\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11"+ + "\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51"+ + "\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51"+ + "\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20"+ + "\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21"+ + "\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\u0090\1\uffff\1\127\12\147\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\53\4\51\1\166\3\51\1\167\4\51\1\165\5\51"+ + "\1\170\5\51\1\164\1\51\1\uffff\1\50\2\uffff\1\51\1\uffff\3\51\1\166\3"+ + "\51\1\167\4\51\1\165\5\51\1\170\5\51\1\164\1\51\1\uffff\1\51\44\uffff"+ + "\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51\1\uffff"+ + "\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4"+ + "\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff"+ + "\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\22\51\1\u0091\10\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\21\51\1\u0091\10\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\24\51\1\u0092\6\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\23\51\1\u0092\6\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\25\51\1\u0093\5\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\24\51\1\u0093\5\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\14\51\1\u0094\16\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\13\51\1\u0094\16\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u0095\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u0095\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\u0096\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\u0096\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\22\51\1\u0097\10\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\21\51\1\u0097\10\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\17\51\1\u0098\13\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\16\51\1\u0098\13\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\1\51\1\u0099\31\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\1\u0099\31\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31"+ + "\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130"+ + "\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51"+ + "\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107"+ + "\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12"+ + "\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1"+ + "\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\16\51\1\u009a\14\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\15\51\1\u009a\14\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\14\51\1\u009c\1\51\1\u009b\14\51\1\uffff\1\50\2\uffff"+ + "\1\51\1\uffff\13\51\1\u009c\1\51\1\u009b\14\51\1\uffff\1\51\44\uffff"+ + "\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\24\51\1\u009e\4\51\1\u009d\1\51\1\uffff\1\50\2\uffff"+ + "\1\51\1\uffff\23\51\1\u009e\4\51\1\u009d\1\51\1\uffff\1\51\44\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\25\51\1\u009f\5\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\24\51\1\u009f\5\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\3\51\1\u00a0\27\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\2\51\1\u00a0\27\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\2\51\1\63\1\62\3\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12"+ + "\60\1\uffff\1\51\1\uffff\1\51\1\uffff\1\53\1\51\32\57\1\uffff\1\64\2"+ + "\uffff\1\61\1\uffff\32\56\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\u00a1\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\32\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00a2\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00a2\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\10\51\1\u00a3\22\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\7\51\1\u00a3\22\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\24\51\1\u00a4\6\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\23\51\1\u00a4\6\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\11\51\1\u00a5\21\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\10\51\1\u00a5\21\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00a6\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00a6\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\16\51\1\u00a7\14\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\15\51\1\u00a7\14\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\22\51\1\u00a8\10\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\21\51\1\u00a8\10\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\24\51\1\u00a9\6\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\23\51\1\u00a9\6\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\25\51\1\u00aa\5\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\24\51\1\u00aa\5\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\14\51\1\u00ab\16\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\13\51\1\u00ab\16\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00ac\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00ac\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\u00ad\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\u00ad\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\22\51\1\u00ae\10\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\21\51\1\u00ae\10\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\17\51\1\u00af\13\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\16\51\1\u00af\13\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\u00b0\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\1\53\4\51\1\166\3\51\1\167\4\51\1\165\5\51\1"+ + "\170\5\51\1\164\1\51\1\uffff\1\50\2\uffff\1\51\1\uffff\3\51\1\166\3\51"+ + "\1\167\4\51\1\165\5\51\1\170\5\51\1\164\1\51\1\uffff\1\51\44\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51"+ + "\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff"+ + "\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff"+ + "\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54"+ + "\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff"+ + "\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff"+ + "\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff"+ + "\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff"+ + "\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f"+ + "\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1"+ + "\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff"+ + "\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2"+ + "\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff"+ + "\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff"+ + "\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3"+ + "\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51"+ + "\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10"+ + "\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff"+ + "\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51"+ + "\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3"+ + "\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1"+ + "\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4"+ + "\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff"+ + "\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2"+ + "\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10"+ + "\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51"+ + "\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51"+ + "\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51"+ + "\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14"+ + "\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1"+ + "\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5"+ + "\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72"+ + "\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44"+ + "\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2"+ + "\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff"+ + "\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff"+ + "\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1"+ + "\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51"+ + "\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125"+ + "\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1"+ + "\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51"+ + "\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51"+ + "\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff"+ + "\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff"+ + "\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff"+ + "\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff"+ + "\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65"+ + "\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51"+ + "\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51"+ + "\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1"+ + "\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00b1\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00b1\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\u00b2\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\u00b2\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00b3\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00b3\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\4\51\1\u00b4\26\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\3\51\1\u00b4\26\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00b5\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00b5\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\10\51\1\u00b6\22\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\7\51\1\u00b6\22\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\24\51\1\u00b7\6\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\23\51\1\u00b7\6\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\11\51\1\u00b8\21\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\10\51\1\u00b8\21\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00b9\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00b9\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\16\51\1\u00ba\14\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\15\51\1\u00ba\14\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\1\127\12\147\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\53\4\51\1\166\3\51\1\167\4\51\1\165\5\51"+ + "\1\170\1\u00bb\4\51\1\164\1\51\1\uffff\1\50\2\uffff\1\51\1\uffff\3\51"+ + "\1\166\3\51\1\167\4\51\1\165\5\51\1\170\5\51\1\164\1\51\1\uffff\1\51"+ + "\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1"+ + "\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51\4\uffff\14"+ + "\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23\51\12\uffff"+ + "\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51\1\uffff\54"+ + "\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff\46\51\2\uffff"+ + "\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff\47\51\1\uffff"+ + "\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff\33\51\5\uffff"+ + "\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff"+ + "\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff"+ + "\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20"+ + "\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff"+ + "\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1"+ + "\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51"+ + "\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1"+ + "\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff"+ + "\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12"+ + "\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51"+ + "\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2"+ + "\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff\14\51\20"+ + "\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51\1\uffff\3"+ + "\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17\uffff\24"+ + "\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12"+ + "\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51"+ + "\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51"+ + "\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff\3\51"+ + "\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12\51\22"+ + "\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20\51\4"+ + "\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51\4\uffff"+ + "\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51\1\uffff"+ + "\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff\10"+ + "\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00bc\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00bc\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\5\51\1\u00bd\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\u00bd\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00be\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00be\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00bf\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00bf\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\5\51\1\u00c0\25\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\4\51\1\u00c0\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00c1\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00c1\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\4\51\1\u00c2\26\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\3\51\1\u00c2\26\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\1\127\12\u00c3\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\32\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\3\51\1\u00c4\27\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\2\51\1\u00c4\27\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00c5\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00c5\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\5\51\1\u00c6\25\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\4\51\1\u00c6\25\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00c7\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00c7\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\1\51\12\u00c8\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\32\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\17\51\1\u00c9\13\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\16\51\1\u00c9\13\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\3\51\1\u00ca\27\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\2\51\1\u00ca\27\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\1\127\12\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\32\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff"+ + "\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff"+ + "\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24"+ + "\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\16\51\1\u00cb\14\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\15\51\1\u00cb\14\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\17\51\1\u00cc\13\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\16\51\1\u00cc\13\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\4\51\1\u00cd\26\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\3\51\1\u00cd\26\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\16\51\1\u00ce\14\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\15\51\1\u00ce\14\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00cf\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00cf\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\51\1\uffff\1\51\1\uffff\13\51\1\uffff\1\51\1\uffff"+ + "\1\51\1\uffff\1\53\4\51\1\u00d0\26\51\1\uffff\1\50\2\uffff\1\51\1\uffff"+ + "\3\51\1\u00d0\26\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b"+ + "\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff"+ + "\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff"+ + "\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff"+ + "\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff"+ + "\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff"+ + "\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff"+ + "\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff"+ + "\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2"+ + "\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2"+ + "\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff"+ + "\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25"+ + "\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51"+ + "\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff"+ + "\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff"+ + "\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2"+ + "\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51"+ + "\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51"+ + "\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2"+ + "\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff"+ + "\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4"+ + "\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51"+ + "\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11"+ + "\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1"+ + "\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff"+ + "\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff"+ + "\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2"+ + "\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27"+ + "\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51"+ + "\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51"+ + "\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1"+ + "\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51"+ + "\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6"+ + "\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff"+ + "\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6"+ + "\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42"+ + "\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1"+ + "\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51"+ + "\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132"+ + "\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff"+ + "\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff"+ + "\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47"+ + "\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff\u0276\51\12"+ + "\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51"+ + "\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64"+ + "\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12"+ + "\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff"+ + "\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff\40\51\u0300"+ + "\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff\26\51\2\uffff"+ + "\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1"+ + "\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51"+ + "\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5"+ + "\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51\10\uffff\11\51"+ + "\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51\2\uffff\11\51"+ + "\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74\51\1\uffff\17"+ + "\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2\uffff\33\51\57"+ + "\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff\145\51\2\uffff"+ + "\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff\34\51\1\uffff"+ + "\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7\51\2\uffff\7"+ + "\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff\26\51\12\uffff"+ + "\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51\u0372\uffff\32"+ + "\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5\uffff\7\51\12\uffff"+ + "\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51\2\uffff\2\51\2\uffff"+ + "\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50\51\70\uffff\57\51\1\uffff"+ + "\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6"+ + "\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff\u2ba4\51\u215c\uffff"+ + "\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff\5\51\5\uffff\32\51"+ + "\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2\51\1\uffff\154\51\41"+ + "\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50\uffff\16\51\2\uffff"+ + "\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51\2\uffff\12\51\1\uffff"+ + "\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1\uffff\u0087\51\4\uffff"+ + "\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51\1\uffff\32\51\1\uffff\1"+ + "\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51\3\uffff\6\51\2\uffff\6\51"+ + "\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\23\51\1\u00d1\7\51\1\uffff\1\50\2\uffff\1\51"+ + "\1\uffff\22\51\1\u00d1\7\51\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\1\51\1\uffff\1\51\1\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff"+ + "\u017b\51\31\uffff\162\51\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21"+ + "\uffff\130\51\5\uffff\23\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1"+ + "\uffff\1\51\1\uffff\24\51\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51"+ + "\1\uffff\107\51\1\uffff\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46"+ + "\51\2\uffff\7\51\1\uffff\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27"+ + "\51\1\uffff\12\51\13\uffff\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff"+ + "\1\51\3\uffff\1\51\1\uffff\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff"+ + "\60\51\2\uffff\73\51\2\uffff\3\51\60\uffff\62\51\u014f\uffff\71\51\2"+ + "\uffff\22\51\2\uffff\5\51\3\uffff\31\51\20\uffff\3\51\1\uffff\10\51\2"+ + "\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff"+ + "\11\51\2\uffff\2\51\2\uffff\3\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\25\51\6\uffff\3\51\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51"+ + "\1\uffff\7\51\1\uffff\2\51\1\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff"+ + "\5\51\4\uffff\2\51\2\uffff\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17"+ + "\51\14\uffff\3\51\1\uffff\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7"+ + "\51\1\uffff\2\51\1\uffff\5\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51"+ + "\2\uffff\1\51\17\uffff\4\51\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51"+ + "\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\5\51\2\uffff\10\51\3\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff"+ + "\2\51\1\uffff\3\51\4\uffff\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3"+ + "\51\1\uffff\4\51\3\uffff\2\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51"+ + "\3\uffff\3\51\3\uffff\10\51\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1"+ + "\uffff\4\51\11\uffff\1\51\17\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1"+ + "\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff"+ + "\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff"+ + "\5\51\2\uffff\11\51\1\uffff\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1"+ + "\51\1\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3"+ + "\51\1\uffff\27\51\1\uffff\20\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51"+ + "\11\uffff\1\51\10\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51"+ + "\3\uffff\30\51\1\uffff\11\51\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4"+ + "\uffff\6\51\1\uffff\1\51\1\uffff\10\51\22\uffff\3\51\14\uffff\72\51\4"+ + "\uffff\35\51\45\uffff\2\51\1\uffff\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff"+ + "\1\51\6\uffff\4\51\1\uffff\7\51\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51"+ + "\2\uffff\2\51\1\uffff\15\51\1\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1"+ + "\uffff\6\51\2\uffff\12\51\2\uffff\2\51\42\uffff\72\51\4\uffff\12\51\1"+ + "\uffff\42\51\6\uffff\33\51\4\uffff\10\51\1\uffff\44\51\1\uffff\17\51"+ + "\2\uffff\1\51\60\uffff\42\51\1\uffff\5\51\1\uffff\2\51\1\uffff\7\51\3"+ + "\uffff\4\51\6\uffff\32\51\106\uffff\46\51\12\uffff\51\51\2\uffff\1\51"+ + "\4\uffff\132\51\5\uffff\104\51\5\uffff\122\51\6\uffff\7\51\1\uffff\77"+ + "\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51"+ + "\2\uffff\47\51\1\uffff\1\51\1\uffff\4\51\2\uffff\37\51\1\uffff\1\51\1"+ + "\uffff\4\51\2\uffff\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff"+ + "\7\51\1\uffff\27\51\1\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7"+ + "\51\1\uffff\47\51\1\uffff\23\51\6\uffff\34\51\43\uffff\125\51\14\uffff"+ + "\u0276\51\12\uffff\32\51\5\uffff\121\51\17\uffff\15\51\1\uffff\7\51\13"+ + "\uffff\27\51\11\uffff\24\51\14\uffff\15\51\1\uffff\3\51\1\uffff\2\51"+ + "\14\uffff\64\51\2\uffff\50\51\2\uffff\12\51\6\uffff\12\51\6\uffff\16"+ + "\51\2\uffff\12\51\6\uffff\130\51\10\uffff\52\51\126\uffff\35\51\3\uffff"+ + "\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff\52\51\2\uffff\5\51\153\uffff"+ + "\40\51\u0300\uffff\154\51\u0094\uffff\u009c\51\4\uffff\132\51\6\uffff"+ + "\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6\51\2\uffff\10\51\1\uffff"+ + "\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51\2\uffff\65\51\1\uffff\7"+ + "\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3\uffff\4\51\2\uffff\6\51"+ + "\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff\10\51\10\uffff\10\51"+ + "\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff\1\51\30\uffff\2\51"+ + "\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff\33\51\25\uffff\74"+ + "\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2\uffff\u0089\51\2"+ + "\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff\u01b8\51\1\uffff"+ + "\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1\uffff\4\51\2\uffff"+ + "\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff\1\51\1\uffff\7"+ + "\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff\16\51\21\uffff"+ + "\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51\2\uffff\u0110\51"+ + "\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51\32\uffff\14\51\5"+ + "\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51\1\uffff\126\51"+ + "\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136\51\1\uffff\50"+ + "\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff\u0080\51\1\uffff"+ + "\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff\67\51\u0739\uffff"+ + "\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095\uffff\7\51\14\uffff"+ + "\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff\2\51\1\uffff\2"+ + "\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2\uffff\66\51\50"+ + "\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51\20\uffff\2\51"+ + "\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51\4\uffff\5\51\1"+ + "\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51\2\uffff\1\51"+ + "\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2\uffff\133\51"+ + "\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff\3\51\1\uffff"+ + "\3\51\1\uffff\7\51", + "\7\51\2\uffff\1\52\1\130\1\uffff\1\130\1\uffff\13\51\1\uffff\1\51\1"+ + "\uffff\1\51\1\uffff\1\53\33\51\1\uffff\1\50\2\uffff\1\51\1\uffff\32\51"+ + "\1\uffff\1\51\44\uffff\7\51\1\uffff\2\51\1\uffff\1\51\1\uffff\1\51\1"+ + "\uffff\4\51\1\uffff\3\51\1\uffff\2\51\1\uffff\u017b\51\31\uffff\162\51"+ + "\4\uffff\14\51\16\uffff\5\51\11\uffff\1\51\21\uffff\130\51\5\uffff\23"+ + "\51\12\uffff\1\51\3\uffff\1\51\7\uffff\5\51\1\uffff\1\51\1\uffff\24\51"+ + "\1\uffff\54\51\1\uffff\54\51\4\uffff\u0087\51\1\uffff\107\51\1\uffff"+ + "\46\51\2\uffff\2\51\6\uffff\20\51\41\uffff\46\51\2\uffff\7\51\1\uffff"+ + "\47\51\1\uffff\2\51\6\uffff\21\51\1\uffff\27\51\1\uffff\12\51\13\uffff"+ + "\33\51\5\uffff\5\51\27\uffff\12\51\5\uffff\1\51\3\uffff\1\51\1\uffff"+ + "\32\51\5\uffff\31\51\7\uffff\175\51\1\uffff\60\51\2\uffff\73\51\2\uffff"+ + "\3\51\60\uffff\62\51\u014f\uffff\71\51\2\uffff\22\51\2\uffff\5\51\3\uffff"+ + "\31\51\20\uffff\3\51\1\uffff\10\51\2\uffff\2\51\2\uffff\26\51\1\uffff"+ + "\7\51\1\uffff\1\51\3\uffff\4\51\2\uffff\11\51\2\uffff\2\51\2\uffff\3"+ + "\51\11\uffff\1\51\4\uffff\2\51\1\uffff\5\51\2\uffff\25\51\6\uffff\3\51"+ + "\1\uffff\6\51\4\uffff\2\51\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1"+ + "\uffff\2\51\1\uffff\2\51\2\uffff\1\51\1\uffff\5\51\4\uffff\2\51\2\uffff"+ + "\3\51\13\uffff\4\51\1\uffff\1\51\7\uffff\17\51\14\uffff\3\51\1\uffff"+ + "\11\51\1\uffff\3\51\1\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5"+ + "\51\2\uffff\12\51\1\uffff\3\51\1\uffff\3\51\2\uffff\1\51\17\uffff\4\51"+ + "\2\uffff\12\51\1\uffff\1\51\17\uffff\3\51\1\uffff\10\51\2\uffff\2\51"+ + "\2\uffff\26\51\1\uffff\7\51\1\uffff\2\51\1\uffff\5\51\2\uffff\10\51\3"+ + "\uffff\2\51\2\uffff\3\51\10\uffff\2\51\4\uffff\2\51\1\uffff\3\51\4\uffff"+ + "\14\51\20\uffff\2\51\1\uffff\6\51\3\uffff\3\51\1\uffff\4\51\3\uffff\2"+ + "\51\1\uffff\1\51\1\uffff\2\51\3\uffff\2\51\3\uffff\3\51\3\uffff\10\51"+ + "\1\uffff\3\51\4\uffff\5\51\3\uffff\3\51\1\uffff\4\51\11\uffff\1\51\17"+ + "\uffff\24\51\6\uffff\3\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1"+ + "\uffff\12\51\1\uffff\5\51\4\uffff\7\51\1\uffff\3\51\1\uffff\4\51\7\uffff"+ + "\2\51\11\uffff\2\51\4\uffff\12\51\22\uffff\2\51\1\uffff\10\51\1\uffff"+ + "\3\51\1\uffff\27\51\1\uffff\12\51\1\uffff\5\51\2\uffff\11\51\1\uffff"+ + "\3\51\1\uffff\4\51\7\uffff\2\51\7\uffff\1\51\1\uffff\2\51\4\uffff\12"+ + "\51\22\uffff\2\51\1\uffff\10\51\1\uffff\3\51\1\uffff\27\51\1\uffff\20"+ + "\51\4\uffff\6\51\2\uffff\3\51\1\uffff\4\51\11\uffff\1\51\10\uffff\2\51"+ + "\4\uffff\12\51\22\uffff\2\51\1\uffff\22\51\3\uffff\30\51\1\uffff\11\51"+ + "\1\uffff\1\51\2\uffff\7\51\3\uffff\1\51\4\uffff\6\51\1\uffff\1\51\1\uffff"+ + "\10\51\22\uffff\3\51\14\uffff\72\51\4\uffff\35\51\45\uffff\2\51\1\uffff"+ + "\1\51\2\uffff\2\51\1\uffff\1\51\2\uffff\1\51\6\uffff\4\51\1\uffff\7\51"+ + "\1\uffff\3\51\1\uffff\1\51\1\uffff\1\51\2\uffff\2\51\1\uffff\15\51\1"+ + "\uffff\3\51\2\uffff\5\51\1\uffff\1\51\1\uffff\6\51\2\uffff\12\51\2\uffff"+ + "\2\51\42\uffff\72\51\4\uffff\12\51\1\uffff\42\51\6\uffff\33\51\4\uffff"+ + "\10\51\1\uffff\44\51\1\uffff\17\51\2\uffff\1\51\60\uffff\42\51\1\uffff"+ + "\5\51\1\uffff\2\51\1\uffff\7\51\3\uffff\4\51\6\uffff\32\51\106\uffff"+ + "\46\51\12\uffff\51\51\2\uffff\1\51\4\uffff\132\51\5\uffff\104\51\5\uffff"+ + "\122\51\6\uffff\7\51\1\uffff\77\51\1\uffff\1\51\1\uffff\4\51\2\uffff"+ + "\7\51\1\uffff\1\51\1\uffff\4\51\2\uffff\47\51\1\uffff\1\51\1\uffff\4"+ + "\51\2\uffff\37\51\1\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\1\51"+ + "\1\uffff\4\51\2\uffff\7\51\1\uffff\7\51\1\uffff\27\51\1\uffff\37\51\1"+ + "\uffff\1\51\1\uffff\4\51\2\uffff\7\51\1\uffff\47\51\1\uffff\23\51\6\uffff"+ + "\34\51\43\uffff\125\51\14\uffff\u0276\51\12\uffff\32\51\5\uffff\121\51"+ + "\17\uffff\15\51\1\uffff\7\51\13\uffff\27\51\11\uffff\24\51\14\uffff\15"+ + "\51\1\uffff\3\51\1\uffff\2\51\14\uffff\64\51\2\uffff\50\51\2\uffff\12"+ + "\51\6\uffff\12\51\6\uffff\16\51\2\uffff\12\51\6\uffff\130\51\10\uffff"+ + "\52\51\126\uffff\35\51\3\uffff\14\51\4\uffff\14\51\4\uffff\1\51\3\uffff"+ + "\52\51\2\uffff\5\51\153\uffff\40\51\u0300\uffff\154\51\u0094\uffff\u009c"+ + "\51\4\uffff\132\51\6\uffff\26\51\2\uffff\6\51\2\uffff\46\51\2\uffff\6"+ + "\51\2\uffff\10\51\1\uffff\1\51\1\uffff\1\51\1\uffff\1\51\1\uffff\37\51"+ + "\2\uffff\65\51\1\uffff\7\51\1\uffff\1\51\3\uffff\3\51\1\uffff\7\51\3"+ + "\uffff\4\51\2\uffff\6\51\4\uffff\15\51\5\uffff\3\51\1\uffff\7\51\23\uffff"+ + "\10\51\10\uffff\10\51\10\uffff\11\51\2\uffff\12\51\2\uffff\16\51\2\uffff"+ + "\1\51\30\uffff\2\51\2\uffff\11\51\2\uffff\16\51\23\uffff\22\51\36\uffff"+ + "\33\51\25\uffff\74\51\1\uffff\17\51\7\uffff\61\51\14\uffff\u0199\51\2"+ + "\uffff\u0089\51\2\uffff\33\51\57\uffff\47\51\31\uffff\13\51\25\uffff"+ + "\u01b8\51\1\uffff\145\51\2\uffff\22\51\16\uffff\2\51\137\uffff\4\51\1"+ + "\uffff\4\51\2\uffff\34\51\1\uffff\43\51\1\uffff\1\51\1\uffff\4\51\3\uffff"+ + "\1\51\1\uffff\7\51\2\uffff\7\51\16\uffff\37\51\3\uffff\30\51\1\uffff"+ + "\16\51\21\uffff\26\51\12\uffff\u0193\51\26\uffff\77\51\4\uffff\40\51"+ + "\2\uffff\u0110\51\u0372\uffff\32\51\1\uffff\131\51\14\uffff\u00d6\51"+ + "\32\uffff\14\51\5\uffff\7\51\12\uffff\2\51\10\uffff\1\51\3\uffff\40\51"+ + "\1\uffff\126\51\2\uffff\2\51\2\uffff\143\51\5\uffff\50\51\4\uffff\136"+ + "\51\1\uffff\50\51\70\uffff\57\51\1\uffff\44\51\14\uffff\56\51\1\uffff"+ + "\u0080\51\1\uffff\u1ab6\51\12\uffff\u51e6\51\132\uffff\u048d\51\3\uffff"+ + "\67\51\u0739\uffff\u2ba4\51\u215c\uffff\u012e\51\2\uffff\73\51\u0095"+ + "\uffff\7\51\14\uffff\5\51\5\uffff\32\51\1\uffff\5\51\1\uffff\1\51\1\uffff"+ + "\2\51\1\uffff\2\51\1\uffff\154\51\41\uffff\u016b\51\22\uffff\100\51\2"+ + "\uffff\66\51\50\uffff\16\51\2\uffff\20\51\20\uffff\4\51\14\uffff\5\51"+ + "\20\uffff\2\51\2\uffff\12\51\1\uffff\5\51\6\uffff\10\51\1\uffff\4\51"+ + "\4\uffff\5\51\1\uffff\u0087\51\4\uffff\7\51\2\uffff\61\51\1\uffff\1\51"+ + "\2\uffff\1\51\1\uffff\32\51\1\uffff\1\51\1\uffff\1\51\2\uffff\1\51\2"+ + "\uffff\133\51\3\uffff\6\51\2\uffff\6\51\2\uffff\6\51\2\uffff\3\51\3\uffff"+ + "\3\51\1\uffff\3\51\1\uffff\7\51" + }; + + static final short[] DFA61_eot = DFA.unpackEncodedString(DFA61_eotS); + static final short[] DFA61_eof = DFA.unpackEncodedString(DFA61_eofS); + static final char[] DFA61_min = DFA.unpackEncodedStringToUnsignedChars(DFA61_minS); + static final char[] DFA61_max = DFA.unpackEncodedStringToUnsignedChars(DFA61_maxS); + static final short[] DFA61_accept = DFA.unpackEncodedString(DFA61_acceptS); + static final short[] DFA61_special = DFA.unpackEncodedString(DFA61_specialS); + static final short[][] DFA61_transition; + + static { + int numStates = DFA61_transitionS.length; + DFA61_transition = new short[numStates][]; + for (int i=0; i= '\u0000' && LA61_52 <= 't')||(LA61_52 >= 'v' && LA61_52 <= '\uFFFF')) ) {s = 78;} + if ( s>=0 ) return s; + break; + + case 1 : + int LA61_32 = input.LA(1); + s = -1; + if ( (LA61_32=='u') ) {s = 64;} + else if ( ((LA61_32 >= '\u0000' && LA61_32 <= 't')||(LA61_32 >= 'v' && LA61_32 <= '\uFFFF')) ) {s = 65;} + if ( s>=0 ) return s; + break; + + case 2 : + int LA61_40 = input.LA(1); + s = -1; + if ( (LA61_40=='u') ) {s = 70;} + else if ( ((LA61_40 >= '\u0000' && LA61_40 <= 't')||(LA61_40 >= 'v' && LA61_40 <= '\uFFFF')) ) {s = 71;} + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 61, _s, input); + error(nvae); + throw nvae; + } + } + +} diff --git a/src/main/java/org/alfresco/repo/search/impl/parsers/FTSParser.java b/src/main/java/org/alfresco/repo/search/impl/parsers/FTSParser.java new file mode 100644 index 0000000000..4603d32e99 --- /dev/null +++ b/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_ftsPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsPrefixed"); + 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: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_ftsPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsPrefixed"); + 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: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_PLUS=new RewriteRuleTokenStream(adaptor,"token PLUS"); + RewriteRuleTokenStream stream_MINUS=new RewriteRuleTokenStream(adaptor,"token MINUS"); + RewriteRuleTokenStream stream_BAR=new RewriteRuleTokenStream(adaptor,"token BAR"); + RewriteRuleSubtreeStream stream_not=new RewriteRuleSubtreeStream(adaptor,"rule not"); + RewriteRuleSubtreeStream stream_ftsTest=new RewriteRuleSubtreeStream(adaptor,"rule ftsTest"); + 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: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_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_template=new RewriteRuleSubtreeStream(adaptor,"rule template"); + RewriteRuleSubtreeStream stream_ftsFieldGroup=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroup"); + RewriteRuleSubtreeStream stream_ftsDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsDisjunction"); + RewriteRuleSubtreeStream stream_ftsRange=new RewriteRuleSubtreeStream(adaptor,"rule ftsRange"); + RewriteRuleSubtreeStream stream_ftsFieldGroupProximity=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupProximity"); + + 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_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\\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_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_PERCENT=new RewriteRuleTokenStream(adaptor,"token PERCENT"); + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + 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_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + 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\\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_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + 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: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: FTSPHRASE, slop, 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(); + // 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: 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(); + // 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: 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(); + // 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_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleTokenStream stream_EQUALS=new RewriteRuleTokenStream(adaptor,"token EQUALS"); + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + 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: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: slop, fieldReference, 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(); + // 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, 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(); + // 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: 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(); + // 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: 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(); + // 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_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleTokenStream stream_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + 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: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: fieldReference, 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(); + // 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: 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(); + // 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: 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(); + // 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: ftsFieldGroupRange, 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(); + // 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_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_fieldReference=new RewriteRuleSubtreeStream(adaptor,"rule fieldReference"); + RewriteRuleSubtreeStream stream_ftsFieldGroupDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupDisjunction"); + + 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_PLUS=new RewriteRuleTokenStream(adaptor,"token PLUS"); + RewriteRuleTokenStream stream_MINUS=new RewriteRuleTokenStream(adaptor,"token MINUS"); + RewriteRuleTokenStream stream_BAR=new RewriteRuleTokenStream(adaptor,"token BAR"); + RewriteRuleSubtreeStream stream_not=new RewriteRuleSubtreeStream(adaptor,"rule not"); + RewriteRuleSubtreeStream stream_boost=new RewriteRuleSubtreeStream(adaptor,"rule boost"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTest=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTest"); + + 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: 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(); + // 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: 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(); + // 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: 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(); + // 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_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_ftsFieldGroupRange=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupRange"); + RewriteRuleSubtreeStream stream_ftsFieldGroupPhrase=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupPhrase"); + 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_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTerm"); + RewriteRuleSubtreeStream stream_ftsFieldGroupSynonym=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupSynonym"); + RewriteRuleSubtreeStream stream_ftsFieldGroupExactTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupExactTerm"); + RewriteRuleSubtreeStream stream_ftsFieldGroupDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupDisjunction"); + RewriteRuleSubtreeStream stream_ftsFieldGroupProximity=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupProximity"); + + 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: fuzzy, 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(); + // 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: fuzzy, ftsFieldGroupExactTerm + // 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: ftsFieldGroupPhrase, 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(); + // 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: slop, 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(); + // 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: ftsFieldGroupTokenisedPhrase, 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(); + // 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_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_STAR=new RewriteRuleTokenStream(adaptor,"token STAR"); + RewriteRuleTokenStream stream_DECIMAL_INTEGER_LITERAL=new RewriteRuleTokenStream(adaptor,"token DECIMAL_INTEGER_LITERAL"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + + 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_range_right=new RewriteRuleSubtreeStream(adaptor,"rule range_right"); + RewriteRuleSubtreeStream stream_ftsRangeWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsRangeWord"); + + 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: range_right, ftsRangeWord, ftsRangeWord, range_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(); + // 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_LT=new RewriteRuleTokenStream(adaptor,"token LT"); + RewriteRuleTokenStream stream_LSQUARE=new RewriteRuleTokenStream(adaptor,"token LSQUARE"); + + 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_GT=new RewriteRuleTokenStream(adaptor,"token GT"); + RewriteRuleTokenStream stream_RSQUARE=new RewriteRuleTokenStream(adaptor,"token RSQUARE"); + + 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_prefix=new RewriteRuleSubtreeStream(adaptor,"rule prefix"); + RewriteRuleSubtreeStream stream_uri=new RewriteRuleSubtreeStream(adaptor,"rule uri"); + 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: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: uri, prefix, 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(); + // 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_prefix=new RewriteRuleSubtreeStream(adaptor,"rule prefix"); + RewriteRuleSubtreeStream stream_uri=new RewriteRuleSubtreeStream(adaptor,"rule uri"); + 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: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: prefix, identifier, 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(); + // 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_AND=new RewriteRuleTokenStream(adaptor,"token AND"); + RewriteRuleTokenStream stream_TO=new RewriteRuleTokenStream(adaptor,"token TO"); + RewriteRuleTokenStream stream_ID=new RewriteRuleTokenStream(adaptor,"token ID"); + RewriteRuleTokenStream stream_DOT=new RewriteRuleTokenStream(adaptor,"token DOT"); + RewriteRuleTokenStream stream_OR=new RewriteRuleTokenStream(adaptor,"token OR"); + + 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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; + } + 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 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 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; + } + + + 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\45\1\73\1\40\1\43\1\44\1\66\1\77\1\54\1\55\1\71\1\63\4\uffff\1\62\10"+ + "\uffff\1\53\1\20\1\56\37\uffff\1\47\1\4\1\2\1\5\1\27\7\uffff\1\41\13\uffff"+ + "\1\17\1\60\1\57\1\65\1\11\1\75\1\12\1\25\1\35\1\31\1\24\10\uffff\1\3\1"+ + "\0\2\uffff\1\1\1\67\1\72\1\42\1\10\1\51\1\52\1\26\1\46\3\uffff\1\37\1"+ + "\34\4\uffff\1\6\34\uffff\1\32\1\33\1\22\1\14\1\7\1\76\3\uffff\1\50\1\15"+ + "\1\13\1\64\1\70\1\16\1\74\4\uffff\1\36\12\uffff\1\23\13\uffff\1\21\1\uffff"+ + "\1\30\1\uffff\1\61}>"; + 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_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 1 : + 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 2 : + 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 3 : + 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 4 : + 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 5 : + 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 6 : + 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 7 : + 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 8 : + 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 9 : + 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 10 : + 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 11 : + 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 12 : + 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 13 : + 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 14 : + 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 15 : + 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 16 : + 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 17 : + 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 18 : + 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 19 : + 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 20 : + 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 21 : + 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 22 : + 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 23 : + 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 24 : + 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 25 : + 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 26 : + 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 27 : + 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 28 : + 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 29 : + 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 30 : + 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 31 : + 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 32 : + 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 33 : + 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 34 : + 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 35 : + 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 36 : + 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 37 : + 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 38 : + 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 39 : + 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 40 : + 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 41 : + 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 42 : + 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 43 : + 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 44 : + 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 45 : + 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 46 : + 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 47 : + 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 48 : + 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 49 : + 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 50 : + 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 51 : + 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 52 : + 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 53 : + 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 54 : + 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 55 : + 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 56 : + 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 57 : + 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 58 : + 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 59 : + 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; + + case 60 : + 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 61 : + 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 62 : + 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 63 : + 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; + } + 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\46\1\uffff\1\61\1\74\2\uffff\1\75\5\uffff\1\24\1\7\1\60\1\77\1\42\5"+ + "\uffff\1\22\1\15\2\uffff\1\55\1\33\1\uffff\1\62\1\21\1\70\1\51\1\12\1"+ + "\54\1\3\1\37\3\uffff\1\100\1\23\1\40\1\4\1\27\1\0\1\43\1\13\1\71\1\25"+ + "\1\64\1\uffff\1\30\1\73\1\26\1\44\1\5\1\32\1\72\1\57\1\20\1\67\1\14\1"+ + "\45\1\50\1\11\1\53\1\2\1\36\1\31\1\101\1\56\1\17\1\66\1\16\1\63\1\47\1"+ + "\10\1\52\1\1\1\35\1\65\1\34\1\6\1\41\1\76}>"; + 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_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 1 : + 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 2 : + 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 3 : + 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 4 : + 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 5 : + 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 6 : + 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 7 : + 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 8 : + 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 9 : + 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 10 : + 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 11 : + 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 12 : + 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 13 : + 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 14 : + 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 15 : + 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; + + case 16 : + 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 17 : + 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 18 : + 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 19 : + 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 20 : + 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 21 : + 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 22 : + 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 23 : + 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 24 : + 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 25 : + 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 26 : + 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 27 : + 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 28 : + 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 29 : + 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 30 : + 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 31 : + 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 32 : + 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 33 : + 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 34 : + 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 35 : + 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 36 : + 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 37 : + 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 38 : + 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 39 : + 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 40 : + 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 41 : + 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 42 : + 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 43 : + 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 44 : + 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 45 : + 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 46 : + 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 47 : + 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 48 : + 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 49 : + 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 50 : + 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 51 : + 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 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_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 54 : + 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 55 : + 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 56 : + 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 57 : + 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 58 : + 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 59 : + 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 60 : + 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 61 : + 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 62 : + 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 63 : + 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 64 : + 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 65 : + 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; + } + 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\44\1\uffff\1\14\1\6\2\uffff\1\24\5\uffff\1\42\1\43\1\53\1\1\1\11\5"+ + "\uffff\1\10\1\101\2\uffff\1\71\1\66\1\uffff\1\52\1\56\1\20\1\63\1\5\1"+ + "\47\1\77\1\27\3\uffff\1\32\1\57\1\21\1\12\1\40\1\33\1\35\1\0\1\41\1\60"+ + "\1\31\1\uffff\1\67\1\13\1\100\1\30\1\73\1\65\1\2\1\51\1\55\1\17\1\70\1"+ + "\34\1\62\1\4\1\46\1\76\1\26\1\64\1\23\1\50\1\54\1\16\1\72\1\22\1\61\1"+ + "\3\1\45\1\75\1\25\1\15\1\74\1\37\1\7\1\36}>"; + 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_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 1 : + 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 2 : + 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 3 : + 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 4 : + 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 5 : + 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 6 : + 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 7 : + 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 8 : + 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 9 : + 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 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_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 12 : + 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; + + case 13 : + 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 14 : + 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 15 : + 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 16 : + 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 17 : + 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 18 : + 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 19 : + 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 20 : + 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 21 : + 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 22 : + 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 23 : + 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 24 : + 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 25 : + 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 26 : + 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 27 : + 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 28 : + 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 29 : + 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 30 : + 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 31 : + 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 32 : + 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 33 : + 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 34 : + 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 35 : + 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 36 : + 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 37 : + 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 38 : + 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 39 : + 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 40 : + 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 41 : + 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 42 : + 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 43 : + 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 44 : + 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 45 : + 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 46 : + 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 47 : + 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 48 : + 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 49 : + 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 50 : + 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 51 : + 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 52 : + 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 53 : + 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 54 : + 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 55 : + 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 56 : + 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 57 : + 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 58 : + 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 59 : + 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 60 : + 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 61 : + 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 62 : + 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 63 : + 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 64 : + 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 65 : + 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; + } + 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\20\1\31\1\34\1\43\1\50\1\33\1\21\1\10\1\12\1\32\1\17\3\uffff\1\35\1"+ + "\4\1\30\3\uffff\1\37\34\uffff\1\6\1\45\1\42\1\36\1\27\70\uffff\1\0\1\14"+ + "\1\3\1\44\1\26\1\47\1\13\1\7\1\2\1\25\1\46\7\uffff\1\23\1\16\32\uffff"+ + "\1\11\1\15\1\1\1\22\1\41\1\5\14\uffff\1\24\12\uffff\1\40\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_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 2 : + 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 3 : + 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 4 : + 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 5 : + 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 6 : + 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 7 : + 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 8 : + 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 9 : + 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 10 : + 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 11 : + 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 12 : + 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 13 : + 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 14 : + 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 15 : + 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 16 : + 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 17 : + 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; + + case 18 : + 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 19 : + 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 20 : + 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 21 : + 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 22 : + 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 23 : + 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 24 : + 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 25 : + 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 26 : + 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 27 : + 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 28 : + 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 29 : + 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 30 : + 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 31 : + 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 32 : + 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 33 : + 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 34 : + 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 35 : + 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 36 : + 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 37 : + 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 38 : + 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 39 : + 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 40 : + 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; + } + 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\u00a8\6\uffff\1\u00f0\6\uffff\1\75\1\26\1\33\1\136\1\u00cb"+ + "\1\62\1\1\1\111\1\144\1\71\1\u00c5\24\uffff\1\u00ae\1\u00a2\1\u00a4\1"+ + "\u0091\1\103\1\u00c0\1\56\1\u00b0\1\165\1\74\1\174\1\154\24\uffff\1\17"+ + "\1\u00ce\1\uffff\1\40\1\50\1\110\1\u008f\1\u00b8\1\u00db\1\25\1\32\1\135"+ + "\1\u00ca\1\61\1\0\1\107\1\143\1\70\1\u00c4\1\u00b6\1\uffff\1\167\1\161"+ + "\1\u00b1\1\u00e7\1\54\1\u00c8\1\u00a3\1\u0090\1\102\1\u00bf\1\55\1\u00af"+ + "\1\164\1\73\1\173\1\153\1\125\1\137\1\134\1\14\1\u00b3\1\u00d2\1\u00e6"+ + "\1\u0084\1\u00a7\1\152\1\115\24\uffff\1\65\5\uffff\1\145\1\4\1\u00f2\1"+ + "\u00c3\1\53\1\u0099\1\172\1\130\1\100\1\u00c2\1\27\24\uffff\1\u00ab\5"+ + "\uffff\1\11\1\30\1\u00f1\1\2\1\35\1\101\1\162\1\u008c\1\106\1\15\1\u00f3"+ + "\1\u00cf\1\u00b2\1\66\1\51\1\u009e\1\175\1\u0085\1\104\1\116\1\u00ee\1"+ + "\u00b9\1\u0097\1\23\1\u0089\24\uffff\1\146\1\u008d\1\u0087\1\42\1\5\1"+ + "\u00d4\1\u00e2\1\u00d0\1\u008e\1\133\1\105\1\u00b4\1\41\24\uffff\1\166"+ + "\1\13\1\u0094\1\126\1\u00de\1\u00c1\1\u00a5\1\176\1\157\1\151\1\u009b"+ + "\1\u00be\1\u00e0\1\10\1\u0096\1\u00ac\1\u00cc\1\u00e4\1\127\1\47\1\uffff"+ + "\1\34\1\u00ed\1\u0088\1\u00e8\1\u00c6\1\u00aa\1\22\1\141\1\64\1\u00c7"+ + "\1\u00e9\1\u00ef\1\171\1\u009c\1\117\1\147\1\u00eb\1\37\1\uffff\1\u00ad"+ + "\1\6\1\46\1\113\1\31\1\u00dc\1\u0080\1\u009d\1\u00b5\1\u00d5\1\123\24"+ + "\uffff\1\132\1\160\1\76\1\140\1\114\1\57\1\u00d9\1\163\1\52\1\u00d7\1"+ + "\u00d1\1\u008b\1\u00d6\1\170\1\122\1\72\1\u009a\1\24\24\uffff\1\45\1\u0083"+ + "\1\36\1\u00a1\1\u00bc\1\u00dd\1\20\1\131\1\u008a\1\u00a9\1\120\1\155\1"+ + "\63\1\u00e3\1\u0093\1\u0098\1\u00bb\1\u00a0\1\77\1\21\1\60\1\112\1\142"+ + "\1\u00ea\1\uffff\1\150\1\u0086\1\u00df\1\u00bd\1\u009f\1\177\1\7\1\156"+ + "\1\u0095\1\67\1\121\1\16\1\124\1\43\1\u00b7\1\u00d3\1\12\1\u0092\1\uffff"+ + "\1\u00e1\1\u00da\1\u00cd\1\u00ec\1\u00c9\1\u00e5\1\3\1\u0081\1\44\1\u00ba"+ + "\1\u00d8\1\u0082\1\u00a6}>"; + 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_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 1 : + 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 2 : + 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 3 : + 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 4 : + 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 5 : + 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 6 : + 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 7 : + 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 8 : + 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 9 : + 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 10 : + 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 11 : + 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 12 : + 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 13 : + 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 14 : + 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 15 : + 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 16 : + 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 17 : + 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 18 : + 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 19 : + 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 20 : + 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 21 : + 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 22 : + 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 23 : + 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 24 : + 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 25 : + 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 26 : + 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 27 : + 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 28 : + 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 29 : + 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 30 : + 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 31 : + 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 32 : + 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 33 : + 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 34 : + 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 35 : + 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 36 : + 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 37 : + 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 38 : + 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 39 : + 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 40 : + 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 41 : + 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 42 : + 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 43 : + 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 44 : + 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 45 : + 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 46 : + 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 47 : + 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 48 : + 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 49 : + 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 50 : + 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 51 : + 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 52 : + 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 53 : + 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 54 : + 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 55 : + 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 56 : + 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 57 : + 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 58 : + 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 59 : + 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 60 : + 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 61 : + 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 62 : + 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 63 : + 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 64 : + 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 65 : + 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 66 : + 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 67 : + 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 68 : + 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 69 : + 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 70 : + 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 71 : + 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 72 : + 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; + + case 73 : + 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 74 : + 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 75 : + 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 76 : + 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 77 : + 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 78 : + 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 79 : + 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 80 : + 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 81 : + 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 82 : + 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 83 : + 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 84 : + 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 85 : + 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 86 : + 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 87 : + 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 88 : + 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 89 : + 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 90 : + 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 91 : + 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 92 : + 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 93 : + 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 94 : + 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 95 : + 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 96 : + 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 97 : + 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 98 : + 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 99 : + 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 100 : + 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 101 : + 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 102 : + 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 103 : + 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 104 : + 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 105 : + 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 106 : + 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 107 : + 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 108 : + 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 109 : + 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 110 : + 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 111 : + 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 112 : + 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 113 : + 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 114 : + 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 115 : + 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 116 : + 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 117 : + 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 118 : + 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 119 : + 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 120 : + 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 121 : + 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 122 : + 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 123 : + 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 124 : + 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 125 : + 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 126 : + 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 127 : + 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 128 : + 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 129 : + 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 130 : + 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 131 : + 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 132 : + 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 133 : + 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 134 : + 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 135 : + 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 136 : + 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 137 : + 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 138 : + 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 139 : + 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 140 : + 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 141 : + 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 142 : + 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 143 : + 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 144 : + 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 145 : + 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 146 : + 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 147 : + 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 148 : + 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 149 : + 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 150 : + 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 151 : + 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 152 : + 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 153 : + 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 154 : + 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 155 : + 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 156 : + 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 157 : + 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 158 : + 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 159 : + 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 160 : + 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 161 : + 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 162 : + 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 163 : + 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 164 : + 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 165 : + 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 166 : + 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 167 : + 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 168 : + 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 169 : + 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 170 : + 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 171 : + 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 172 : + 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 173 : + 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 174 : + 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 175 : + 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 176 : + 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 177 : + 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 178 : + 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 179 : + 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 180 : + 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 181 : + 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 182 : + 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 183 : + 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 184 : + 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 185 : + 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 186 : + 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 187 : + 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 188 : + 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 189 : + 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 190 : + 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 191 : + 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 192 : + 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 193 : + 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 194 : + 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 195 : + 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 196 : + 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 197 : + 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 198 : + 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 199 : + 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 200 : + 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 201 : + 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 202 : + 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 203 : + 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 204 : + 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 205 : + 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 206 : + 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 207 : + 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 208 : + 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 209 : + 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 210 : + 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 211 : + 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 212 : + 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 213 : + 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 214 : + 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 215 : + 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 216 : + 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 217 : + 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 218 : + 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 219 : + 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 220 : + 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 221 : + 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 222 : + 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 223 : + 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 224 : + 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 225 : + 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 226 : + 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 227 : + 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 228 : + 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 229 : + 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 230 : + 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 231 : + 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 232 : + 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 233 : + 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 234 : + 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 235 : + 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 236 : + 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 237 : + 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 238 : + 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 239 : + 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 240 : + 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 241 : + 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 242 : + 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 243 : + 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; + } + 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/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryException.java b/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryException.java new file mode 100644 index 0000000000..898f08669c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java b/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java new file mode 100644 index 0000000000..e7d8f4ee9d --- /dev/null +++ b/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) + { + 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/src/main/java/org/alfresco/repo/search/impl/parsers/GenerateUnicodeRanges.java b/src/main/java/org/alfresco/repo/search/impl/parsers/GenerateUnicodeRanges.java new file mode 100644 index 0000000000..5ee226a89c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Argument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Argument.java new file mode 100644 index 0000000000..6f89cfc348 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/ArgumentDefinition.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/ArgumentDefinition.java new file mode 100644 index 0000000000..c190589043 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Column.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Column.java new file mode 100644 index 0000000000..0dcfe34962 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Conjunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Conjunction.java new file mode 100644 index 0000000000..3a83f86857 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Constraint.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Constraint.java new file mode 100644 index 0000000000..f4fdda1c49 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Disjunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Disjunction.java new file mode 100644 index 0000000000..a90ba95434 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/DynamicArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/DynamicArgument.java new file mode 100644 index 0000000000..9d0720e109 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Function.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Function.java new file mode 100644 index 0000000000..9700ee15ef --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionArgument.java new file mode 100644 index 0000000000..ebae7bb29b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionEvaluationContext.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionEvaluationContext.java new file mode 100644 index 0000000000..44fc1080bf --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionInvokation.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionInvokation.java new file mode 100644 index 0000000000..c5d0103bd1 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionalConstraint.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionalConstraint.java new file mode 100644 index 0000000000..4913c92319 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Join.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Join.java new file mode 100644 index 0000000000..a36c672adf --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/Join.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; + +/** + * @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 type + * @return JoinType + */ + public JoinType getJoinType(); + + /** + * Get the join condition. + * Not all constraints are valid join conditions + * @return Constraint + */ + public Constraint getJoinCondition(); +} diff --git a/src/main/java/org/alfresco/repo/search/impl/querymodel/JoinType.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/JoinType.java new file mode 100644 index 0000000000..f6ed531093 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/JoinType.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 enum JoinType +{ + /** + * Inner join + */ + INNER, + /** + * Left (outer) join + */ + LEFT, + /** + * Right (outer) join + */ + RIGHT +} diff --git a/src/main/java/org/alfresco/repo/search/impl/querymodel/ListArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/ListArgument.java new file mode 100644 index 0000000000..1a385186e4 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/LiteralArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/LiteralArgument.java new file mode 100644 index 0000000000..c963e0a463 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Multiplicity.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Multiplicity.java new file mode 100644 index 0000000000..4c714846dc --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Order.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Order.java new file mode 100644 index 0000000000..05ce23ae4a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Ordering.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Ordering.java new file mode 100644 index 0000000000..5e660fa5e9 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/ParameterArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/ParameterArgument.java new file mode 100644 index 0000000000..13f65a0fd9 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/PredicateMode.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/PredicateMode.java new file mode 100644 index 0000000000..e7274763c0 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/PropertyArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/PropertyArgument.java new file mode 100644 index 0000000000..49d5886f68 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Query.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Query.java new file mode 100644 index 0000000000..1f0c104b06 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngine.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngine.java new file mode 100644 index 0000000000..e543104e5f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngineResults.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngineResults.java new file mode 100644 index 0000000000..9349f38709 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelException.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelException.java new file mode 100644 index 0000000000..cdede6e330 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelFactory.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelFactory.java new file mode 100644 index 0000000000..3db026ede3 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryOptions.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryOptions.java new file mode 100644 index 0000000000..bbbb8f4dc5 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryOptions.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.repo.search.impl.querymodel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +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; + + 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()); + 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; + } + + /** + * @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()); + return searchParameters; + } + +} diff --git a/src/main/java/org/alfresco/repo/search/impl/querymodel/Selector.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Selector.java new file mode 100644 index 0000000000..c3bd3c8c3b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/SelectorArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/SelectorArgument.java new file mode 100644 index 0000000000..db752d7ba1 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/Source.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/Source.java new file mode 100644 index 0000000000..b6e206fa13 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/Source.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 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); +} diff --git a/src/main/java/org/alfresco/repo/search/impl/querymodel/StaticArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/StaticArgument.java new file mode 100644 index 0000000000..49203ed2a9 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgument.java new file mode 100644 index 0000000000..3b56965d7a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgumentDefinition.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgumentDefinition.java new file mode 100644 index 0000000000..bac24e9528 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseColumn.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseColumn.java new file mode 100644 index 0000000000..0bf1de7805 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseComparison.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseComparison.java new file mode 100644 index 0000000000..02be173223 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConjunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConjunction.java new file mode 100644 index 0000000000..f7129fb825 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConstraint.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConstraint.java new file mode 100644 index 0000000000..ab6eb5c7db --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDisjunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDisjunction.java new file mode 100644 index 0000000000..bb1bf4f765 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDynamicArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDynamicArgument.java new file mode 100644 index 0000000000..3b6a222a9b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunction.java new file mode 100644 index 0000000000..71d1c64b4e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionArgument.java new file mode 100644 index 0000000000..08b1f2c74b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionalConstraint.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionalConstraint.java new file mode 100644 index 0000000000..b706136fa8 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseJoin.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseJoin.java new file mode 100644 index 0000000000..0108004df9 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseJoin.java @@ -0,0 +1,250 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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) && (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; + } +} diff --git a/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseListArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseListArgument.java new file mode 100644 index 0000000000..0baa8cb05b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseLiteralArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseLiteralArgument.java new file mode 100644 index 0000000000..f6156bda40 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseOrdering.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseOrdering.java new file mode 100644 index 0000000000..f8a196b7a8 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseParameterArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseParameterArgument.java new file mode 100644 index 0000000000..454f7fcb58 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BasePropertyArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BasePropertyArgument.java new file mode 100644 index 0000000000..97c9dd985b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseQuery.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseQuery.java new file mode 100644 index 0000000000..033a39611d --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelector.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelector.java new file mode 100644 index 0000000000..ec0e1f0c34 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelector.java @@ -0,0 +1,116 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.Selector; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public class BaseSelector implements Selector +{ + private QName type; + + private String alias; + + public BaseSelector(QName type, String alias) + { + this.type = type; + this.alias = alias; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Selector#getAlias() + */ + public String getAlias() + { + return alias; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Selector#getType() + */ + 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()); + 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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelectorArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelectorArgument.java new file mode 100644 index 0000000000..ce97bb7646 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseStaticArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseStaticArgument.java new file mode 100644 index 0000000000..4b7fc5cbef --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/DuplicateSelectorNameException.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/DuplicateSelectorNameException.java new file mode 100644 index 0000000000..d2688a748b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/SimpleConstraint.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/SimpleConstraint.java new file mode 100644 index 0000000000..c3dcb3c91a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Child.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Child.java new file mode 100644 index 0000000000..2f9446a72c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Descendant.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Descendant.java new file mode 100644 index 0000000000..bc1709f0b5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Equals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Equals.java new file mode 100644 index 0000000000..3382632e5f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Exists.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Exists.java new file mode 100644 index 0000000000..bb42d1fcad --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSFuzzyTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSFuzzyTerm.java new file mode 100644 index 0000000000..9ee05d8b15 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPhrase.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPhrase.java new file mode 100644 index 0000000000..b2b3919167 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPrefixTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPrefixTerm.java new file mode 100644 index 0000000000..97d6d66690 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java new file mode 100644 index 0000000000..0f3fbee3de --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java new file mode 100644 index 0000000000..95e8407630 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSTerm.java new file mode 100644 index 0000000000..f1cd86691e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSWildTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSWildTerm.java new file mode 100644 index 0000000000..8a93cb4187 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThan.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThan.java new file mode 100644 index 0000000000..05281d8793 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThanOrEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThanOrEquals.java new file mode 100644 index 0000000000..102e593c12 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/In.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/In.java new file mode 100644 index 0000000000..e52b0860fd --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThan.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThan.java new file mode 100644 index 0000000000..698d4d639f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThanOrEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThanOrEquals.java new file mode 100644 index 0000000000..a05b467809 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Like.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Like.java new file mode 100644 index 0000000000..c7a779e0b4 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Lower.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Lower.java new file mode 100644 index 0000000000..dc6dd42c15 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/NotEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/NotEquals.java new file mode 100644 index 0000000000..c8cd6bcf4e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/PropertyAccessor.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/PropertyAccessor.java new file mode 100644 index 0000000000..661dcb94d2 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Score.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Score.java new file mode 100644 index 0000000000..dcc7002483 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Upper.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Upper.java new file mode 100644 index 0000000000..0b70087025 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneColumn.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneColumn.java new file mode 100644 index 0000000000..4ef1a8ee10 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java new file mode 100644 index 0000000000..9f333ebcc8 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java new file mode 100644 index 0000000000..25722570b5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionArgument.java new file mode 100644 index 0000000000..c2bec8bdd0 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionalConstraint.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionalConstraint.java new file mode 100644 index 0000000000..7892f29033 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneJoin.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneJoin.java new file mode 100644 index 0000000000..7afd642079 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneListArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneListArgument.java new file mode 100644 index 0000000000..07de2bac27 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneLiteralArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneLiteralArgument.java new file mode 100644 index 0000000000..9820b6dcbc --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneOrdering.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneOrdering.java new file mode 100644 index 0000000000..3b186c97a1 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneParameterArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneParameterArgument.java new file mode 100644 index 0000000000..82d53e5909 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java new file mode 100644 index 0000000000..975069663f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java new file mode 100644 index 0000000000..2ce6973cf1 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java new file mode 100644 index 0000000000..c0f3e4946a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java new file mode 100644 index 0000000000..bb3683d969 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java new file mode 100644 index 0000000000..65b37de379 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java new file mode 100644 index 0000000000..fb8385d12b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelector.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelector.java new file mode 100644 index 0000000000..1f2f62b510 --- /dev/null +++ b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelector.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.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.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(); + return lqpa.getFieldQuery("CLASS", getType().toString()); + + } + + +} diff --git a/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelectorArgument.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelectorArgument.java new file mode 100644 index 0000000000..6a30bce61b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneChild.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneChild.java new file mode 100644 index 0000000000..52c8b70f3f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneDescendant.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneDescendant.java new file mode 100644 index 0000000000..48ad0577a6 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneEquals.java new file mode 100644 index 0000000000..b623b89a1e --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneExists.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneExists.java new file mode 100644 index 0000000000..744aced99c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java new file mode 100644 index 0000000000..a98ea4c7da --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPhrase.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPhrase.java new file mode 100644 index 0000000000..c296b6ceb5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java new file mode 100644 index 0000000000..d0ce618ecf --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java new file mode 100644 index 0000000000..7d1c45461c --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java new file mode 100644 index 0000000000..5979d52cd9 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSTerm.java new file mode 100644 index 0000000000..740539049a --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java new file mode 100644 index 0000000000..5c886112c7 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThan.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThan.java new file mode 100644 index 0000000000..508184f4e5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThanOrEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThanOrEquals.java new file mode 100644 index 0000000000..4b7f7df0ca --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneIn.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneIn.java new file mode 100644 index 0000000000..4986b40dd0 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThan.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThan.java new file mode 100644 index 0000000000..307f7799df --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThanOrEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThanOrEquals.java new file mode 100644 index 0000000000..b8161dd238 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLike.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLike.java new file mode 100644 index 0000000000..aa0dac3e8f --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLower.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLower.java new file mode 100644 index 0000000000..11a4c86d53 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneNotEquals.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneNotEquals.java new file mode 100644 index 0000000000..29bdd63c04 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LucenePropertyAccessor.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LucenePropertyAccessor.java new file mode 100644 index 0000000000..922b880138 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneScore.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneScore.java new file mode 100644 index 0000000000..8407d39021 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneUpper.java b/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneUpper.java new file mode 100644 index 0000000000..330ccd78a3 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContext.java b/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContext.java new file mode 100644 index 0000000000..fa326aedfd --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java b/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java new file mode 100644 index 0000000000..5f16e38ae2 --- /dev/null +++ b/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java @@ -0,0 +1,157 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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; + +/** + * Hold an Alfresco extended security context + * + * @author andyh + * + */ +public class AlfrescoSecureContextImpl implements AlfrescoSecureContext +{ + 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) + { + this.effectiveAuthentication = effictiveAuthentication; + } + + public void setRealAuthentication(Authentication 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 authenticaion = null"); + } + else + { + builder.append("Real authenticaion = " + realAuthentication.toString()); + } + builder.append(", "); + + if (effectiveAuthentication == null) + { + builder.append("Effective authenticaion = null"); + } + else + { + builder.append("Effective authenticaion = " + effectiveAuthentication.toString()); + } + builder.append(", "); + + return builder.toString(); + } + +} diff --git a/src/main/java/org/alfresco/repo/security/authentication/AuthenticationDiagnostic.java b/src/main/java/org/alfresco/repo/security/authentication/AuthenticationDiagnostic.java new file mode 100644 index 0000000000..fc1baacd70 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/security/authentication/AuthenticationException.java b/src/main/java/org/alfresco/repo/security/authentication/AuthenticationException.java new file mode 100644 index 0000000000..107692619d --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/security/authentication/AuthenticationStep.java b/src/main/java/org/alfresco/repo/security/authentication/AuthenticationStep.java new file mode 100644 index 0000000000..2152f982e3 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java b/src/main/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java new file mode 100644 index 0000000000..6c288247f0 --- /dev/null +++ b/src/main/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java @@ -0,0 +1,724 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 s_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 (s_logger.isDebugEnabled()) + s_logger.debug("MT is enabled: " + mtEnabled); + AuthenticationUtil.mtEnabled = mtEnabled; + } + + public static boolean isMtEnabled() + { + return AuthenticationUtil.mtEnabled; + } + + 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 (s_logger.isDebugEnabled()) + s_logger.debug("Setting fully authenticated principal: " + authentication.getName()); + Context context = ContextHolder.getContext(); + AlfrescoSecureContext sc = null; + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + if (s_logger.isDebugEnabled()) + s_logger.debug("Creating new secure context."); + sc = new AlfrescoSecureContextImpl(); + ContextHolder.setContext(sc); + } + 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 (s_logger.isDebugEnabled()) + s_logger.debug("Setting RunAs principal: " + authentication.getName()); + Context context = ContextHolder.getContext(); + AlfrescoSecureContext sc = null; + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + if (s_logger.isDebugEnabled()) + s_logger.debug("Creating new secure context."); + sc = new AlfrescoSecureContextImpl(); + ContextHolder.setContext(sc); + } + else + { + sc = (AlfrescoSecureContext) context; + } + authentication.setAuthenticated(true); + if (sc.getRealAuthentication() == null) + { + if (s_logger.isDebugEnabled()) + s_logger.debug("There is no fully authenticated prinipal. Setting fully authenticated principal: " + authentication.getName()); + 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 (s_logger.isDebugEnabled()) + s_logger.debug("Removing the current security information."); + 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()); + } + + /** + * 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); + } + + /** + * Logs the current authenticated users + */ + public static void logAuthenticatedUsers() + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug( + "Authentication: \n" + + " Fully authenticated: " + AuthenticationUtil.getFullyAuthenticatedUser() + "\n" + + " Run as: " + AuthenticationUtil.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:" + userName); + } + else + { + NDC.push("User:" + userName); + } + } + else + { + NDC.push("User:" + 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 (s_logger.isDebugEnabled()) + { + s_logger.debug("Tenant domain implied: userName="+userName+", tenantDomain="+tenantDomain); + } + } + } + } + return new Pair(userName, tenantDomain); + } +} diff --git a/src/main/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java b/src/main/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java new file mode 100644 index 0000000000..062d7867fb --- /dev/null +++ b/src/main/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java @@ -0,0 +1,574 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.safehaus.uuid.UUIDGenerator; + +/** + * 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 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 + */ + public void setOneOff(boolean oneOff) + { + this.oneOff = oneOff; + } + + /** + * 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); + } + + @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); + ticketsCache.put(ticket.getTicketId(), ticket); + } + + String ticketString = GRANTED_AUTHORITY_TICKET_PREFIX + ticket.getTicketId(); + currentTicket.set(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) + { + ticketsCache.put(key, newTicket); + } + return ticket; + } + } + } + } + return null; + } + + @Override + public String validateTicket(String ticketString) throws AuthenticationException + { + String ticketKey = getTicketKey(ticketString); + Ticket ticket = ticketsCache.get(ticketKey); + if (ticket == null) + { + throw new AuthenticationException("Missing ticket for " + ticketString); + } + Ticket newTicket = ticket.getNewEntry(); + if (newTicket == null) + { + throw new TicketExpiredException("Ticket expired for " + ticketString); + } + if (oneOff) + { + ticketsCache.remove(ticketKey); + } + else if (newTicket != ticket) + { + ticketsCache.put(ticketKey, newTicket); + } + currentTicket.set(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()); + ticketsCache.remove(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) + { + Date now = new Date(); + int count = 0; + if (!expiredOnly) + { + count = ticketsCache.getKeys().size(); + 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) + { + ticketsCache.remove(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) + { + ticketsCache.remove(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) + { + this.expires = expires; + this.expiryDate = expiryDate; + this.userName = userName; + this.validDuration = validDuration; + this.testDuration = validDuration.divide(2); + final String guid = UUIDGenerator.getInstance().generateRandomBasedUUID().toString(); + + String encode = (expires.toString()) + ((expiryDate == null) ? new Date().toString() : expiryDate.toString()) + 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)); + } + } + this.ticketId = ticketId; + } + + private Ticket(ExpiryMode expires, Date expiryDate, String userName, Duration validDuration, String 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; + } + + 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) + { + 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.expires == t.expires) && this.expiryDate.equals(t.expiryDate) && this.userName.equals(t.userName) && this.ticketId.equals(t.ticketId); + } + + 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 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() + { + currentTicket.set(null); + } + + public enum ExpiryMode + { + AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE; + } +} diff --git a/src/main/java/org/alfresco/repo/security/authentication/TicketComponent.java b/src/main/java/org/alfresco/repo/security/authentication/TicketComponent.java new file mode 100644 index 0000000000..29a16c2c80 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/security/authentication/TicketExpiredException.java b/src/main/java/org/alfresco/repo/security/authentication/TicketExpiredException.java new file mode 100644 index 0000000000..8daa738a75 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/SingleTServiceImpl.java b/src/main/java/org/alfresco/repo/tenant/SingleTServiceImpl.java new file mode 100644 index 0000000000..9d124d7f20 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/Tenant.java b/src/main/java/org/alfresco/repo/tenant/Tenant.java new file mode 100644 index 0000000000..cfbc89793b --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/TenantContextHolder.java b/src/main/java/org/alfresco/repo/tenant/TenantContextHolder.java new file mode 100644 index 0000000000..349ec6af11 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/TenantDeployer.java b/src/main/java/org/alfresco/repo/tenant/TenantDeployer.java new file mode 100644 index 0000000000..fbee505a53 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/TenantService.java b/src/main/java/org/alfresco/repo/tenant/TenantService.java new file mode 100644 index 0000000000..d97606d6fa --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/TenantUserService.java b/src/main/java/org/alfresco/repo/tenant/TenantUserService.java new file mode 100644 index 0000000000..5bff9a8ed5 --- /dev/null +++ b/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/src/main/java/org/alfresco/repo/tenant/TenantUtil.java b/src/main/java/org/alfresco/repo/tenant/TenantUtil.java new file mode 100644 index 0000000000..ab68c7d2e7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/Auditable.java b/src/main/java/org/alfresco/service/Auditable.java new file mode 100644 index 0000000000..9fc3bf4c24 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/NotAuditable.java b/src/main/java/org/alfresco/service/NotAuditable.java new file mode 100644 index 0000000000..ce4376e164 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/PublicService.java b/src/main/java/org/alfresco/service/PublicService.java new file mode 100644 index 0000000000..e46c2b939c --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/AspectDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/AspectDefinition.java new file mode 100644 index 0000000000..9d8a0d8618 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/AssociationDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/AssociationDefinition.java new file mode 100644 index 0000000000..d5a232463e --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/ChildAssociationDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/ChildAssociationDefinition.java new file mode 100644 index 0000000000..3d985bf408 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/ClassAttributeDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/ClassAttributeDefinition.java new file mode 100644 index 0000000000..3c7a959a80 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/ClassDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/ClassDefinition.java new file mode 100644 index 0000000000..0534878ad2 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/Constraint.java b/src/main/java/org/alfresco/service/cmr/dictionary/Constraint.java new file mode 100644 index 0000000000..be58cc7d8b --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintDefinition.java new file mode 100644 index 0000000000..95581ecafd --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintException.java b/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintException.java new file mode 100644 index 0000000000..1f5d4122fc --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelDefinition.java new file mode 100644 index 0000000000..9faeb01664 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelException.java b/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelException.java new file mode 100644 index 0000000000..200bc2bff8 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelService.java b/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelService.java new file mode 100644 index 0000000000..f1864b2c14 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java new file mode 100644 index 0000000000..98bfdd8692 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryException.java b/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryException.java new file mode 100644 index 0000000000..28f4ee4232 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryService.java b/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryService.java new file mode 100644 index 0000000000..8d1d0467e1 --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryService.java @@ -0,0 +1,327 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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; + +import com.sun.tools.xjc.outline.Aspect; + + + +/** + * 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 (or null, if it doesn't exist) + */ + @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); + + // TODO: Behaviour definitions + +} diff --git a/src/main/java/org/alfresco/service/cmr/dictionary/InvalidAspectException.java b/src/main/java/org/alfresco/service/cmr/dictionary/InvalidAspectException.java new file mode 100644 index 0000000000..8b7a447f8e --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/InvalidClassException.java b/src/main/java/org/alfresco/service/cmr/dictionary/InvalidClassException.java new file mode 100644 index 0000000000..f8d3184a67 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/InvalidTypeException.java b/src/main/java/org/alfresco/service/cmr/dictionary/InvalidTypeException.java new file mode 100644 index 0000000000..ecc39ec779 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/ModelDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/ModelDefinition.java new file mode 100644 index 0000000000..01ea8ca9e5 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java new file mode 100644 index 0000000000..ca27ed2293 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java new file mode 100644 index 0000000000..7d44f8e370 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/dictionary/TypeDefinition.java b/src/main/java/org/alfresco/service/cmr/dictionary/TypeDefinition.java new file mode 100644 index 0000000000..9e2fc91305 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/i18n/MessageLookup.java b/src/main/java/org/alfresco/service/cmr/i18n/MessageLookup.java new file mode 100644 index 0000000000..ce9d19f2f7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/AbstractStoreException.java b/src/main/java/org/alfresco/service/cmr/repository/AbstractStoreException.java new file mode 100644 index 0000000000..5f4ebc1b04 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/AssociationExistsException.java b/src/main/java/org/alfresco/service/cmr/repository/AssociationExistsException.java new file mode 100644 index 0000000000..cdba07bbfc --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/AssociationRef.java b/src/main/java/org/alfresco/service/cmr/repository/AssociationRef.java new file mode 100644 index 0000000000..30f07b1d97 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ChildAssociationRef.java b/src/main/java/org/alfresco/service/cmr/repository/ChildAssociationRef.java new file mode 100644 index 0000000000..7183cf6bbd --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentAccessor.java b/src/main/java/org/alfresco/service/cmr/repository/ContentAccessor.java new file mode 100644 index 0000000000..21051b42a6 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentData.java b/src/main/java/org/alfresco/service/cmr/repository/ContentData.java new file mode 100644 index 0000000000..d9f4f91341 --- /dev/null +++ b/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.springframework.extensions.surf.util.I18NUtil; +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.util.EqualsHelper; + +/** + * 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" + + " mimetype: " + mimetype); + } + } + } + + /** + * 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/src/main/java/org/alfresco/service/cmr/repository/ContentIOException.java b/src/main/java/org/alfresco/service/cmr/repository/ContentIOException.java new file mode 100644 index 0000000000..2135a3194e --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentReader.java b/src/main/java/org/alfresco/service/cmr/repository/ContentReader.java new file mode 100644 index 0000000000..330ce9c1d3 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentServiceTransientException.java b/src/main/java/org/alfresco/service/cmr/repository/ContentServiceTransientException.java new file mode 100644 index 0000000000..e6ced0455b --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentStreamListener.java b/src/main/java/org/alfresco/service/cmr/repository/ContentStreamListener.java new file mode 100644 index 0000000000..c90c997853 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentUrlKey.java b/src/main/java/org/alfresco/service/cmr/repository/ContentUrlKey.java new file mode 100644 index 0000000000..8f9230e6c6 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/ContentWriter.java b/src/main/java/org/alfresco/service/cmr/repository/ContentWriter.java new file mode 100644 index 0000000000..621daf98fb --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/EntityRef.java b/src/main/java/org/alfresco/service/cmr/repository/EntityRef.java new file mode 100644 index 0000000000..12475bef80 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/FileContentReader.java b/src/main/java/org/alfresco/service/cmr/repository/FileContentReader.java new file mode 100644 index 0000000000..f3b8b39cfc --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/InvalidChildAssociationRefException.java b/src/main/java/org/alfresco/service/cmr/repository/InvalidChildAssociationRefException.java new file mode 100644 index 0000000000..2b1066ba05 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/InvalidNodeRefException.java b/src/main/java/org/alfresco/service/cmr/repository/InvalidNodeRefException.java new file mode 100644 index 0000000000..e79fc36af7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/InvalidStoreRefException.java b/src/main/java/org/alfresco/service/cmr/repository/InvalidStoreRefException.java new file mode 100644 index 0000000000..82a4201f1a --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/MLText.java b/src/main/java/org/alfresco/service/cmr/repository/MLText.java new file mode 100644 index 0000000000..7825628f38 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/MalformedNodeRefException.java b/src/main/java/org/alfresco/service/cmr/repository/MalformedNodeRefException.java new file mode 100644 index 0000000000..138fc331bc --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/MimetypeService.java b/src/main/java/org/alfresco/service/cmr/repository/MimetypeService.java new file mode 100644 index 0000000000..c1c03aa3e7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/MimetypeServiceAware.java b/src/main/java/org/alfresco/service/cmr/repository/MimetypeServiceAware.java new file mode 100644 index 0000000000..f65140d16c --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/NodeRef.java b/src/main/java/org/alfresco/service/cmr/repository/NodeRef.java new file mode 100644 index 0000000000..c940359d51 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/NodeService.java b/src/main/java/org/alfresco/service/cmr/repository/NodeService.java new file mode 100644 index 0000000000..d4ed87fce8 --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/repository/NodeService.java @@ -0,0 +1,998 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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. + * + * @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. + * + * @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/src/main/java/org/alfresco/service/cmr/repository/Path.java b/src/main/java/org/alfresco/service/cmr/repository/Path.java new file mode 100644 index 0000000000..57a7b4a874 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/Period.java b/src/main/java/org/alfresco/service/cmr/repository/Period.java new file mode 100644 index 0000000000..54d771d9e6 --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/repository/Period.java @@ -0,0 +1,189 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.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. + * + * @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]; + } + } + + /** + * @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/src/main/java/org/alfresco/service/cmr/repository/PeriodProvider.java b/src/main/java/org/alfresco/service/cmr/repository/PeriodProvider.java new file mode 100644 index 0000000000..e71b5fd276 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/StoreExistsException.java b/src/main/java/org/alfresco/service/cmr/repository/StoreExistsException.java new file mode 100644 index 0000000000..522b16f999 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/StoreRef.java b/src/main/java/org/alfresco/service/cmr/repository/StoreRef.java new file mode 100644 index 0000000000..c6a4d8898c --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/XPathException.java b/src/main/java/org/alfresco/service/cmr/repository/XPathException.java new file mode 100644 index 0000000000..87d4d5aa34 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java b/src/main/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java new file mode 100644 index 0000000000..083951f23a --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java @@ -0,0 +1,843 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; +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.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(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); + + // + // Content Reader + // + 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(); + } + }); + + // + // Content Writer + // + addConverter(ContentWriter.class, String.class, new TypeConverter.Converter() + { + public String convert(ContentWriter source) + { + return source.toString(); + } + }); + + // + // Input Stream + // + 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); + + } + +} diff --git a/src/main/java/org/alfresco/service/cmr/repository/datatype/Duration.java b/src/main/java/org/alfresco/service/cmr/repository/datatype/Duration.java new file mode 100644 index 0000000000..40637a6177 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConversionException.java b/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConversionException.java new file mode 100644 index 0000000000..a2818aff6c --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConverter.java b/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConverter.java new file mode 100644 index 0000000000..3592bcbae7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/BasicSearchParameters.java b/src/main/java/org/alfresco/service/cmr/search/BasicSearchParameters.java new file mode 100644 index 0000000000..d6cb10047d --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/LimitBy.java b/src/main/java/org/alfresco/service/cmr/search/LimitBy.java new file mode 100644 index 0000000000..50f8107395 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/NamedQueryParameterDefinition.java b/src/main/java/org/alfresco/service/cmr/search/NamedQueryParameterDefinition.java new file mode 100644 index 0000000000..c66f71b392 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/PermissionEvaluationMode.java b/src/main/java/org/alfresco/service/cmr/search/PermissionEvaluationMode.java new file mode 100644 index 0000000000..00d2a953b9 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/QueryConsistency.java b/src/main/java/org/alfresco/service/cmr/search/QueryConsistency.java new file mode 100644 index 0000000000..66b6fd8584 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/QueryParameter.java b/src/main/java/org/alfresco/service/cmr/search/QueryParameter.java new file mode 100644 index 0000000000..43406e8339 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/QueryParameterDefinition.java b/src/main/java/org/alfresco/service/cmr/search/QueryParameterDefinition.java new file mode 100644 index 0000000000..34f8b15780 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/ResultSet.java b/src/main/java/org/alfresco/service/cmr/search/ResultSet.java new file mode 100644 index 0000000000..0275223243 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/ResultSetColumn.java b/src/main/java/org/alfresco/service/cmr/search/ResultSetColumn.java new file mode 100644 index 0000000000..ec836ee7c9 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/ResultSetMetaData.java b/src/main/java/org/alfresco/service/cmr/search/ResultSetMetaData.java new file mode 100644 index 0000000000..c4b57726a4 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/ResultSetRow.java b/src/main/java/org/alfresco/service/cmr/search/ResultSetRow.java new file mode 100644 index 0000000000..4f76cae815 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/ResultSetSPI.java b/src/main/java/org/alfresco/service/cmr/search/ResultSetSPI.java new file mode 100644 index 0000000000..c1517f72df --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/search/ResultSetSPI.java @@ -0,0 +1,197 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 spell check result + * + * @return SpellCheckResult + */ + public SpellCheckResult getSpellCheckResult(); +} diff --git a/src/main/java/org/alfresco/service/cmr/search/ResultSetSelector.java b/src/main/java/org/alfresco/service/cmr/search/ResultSetSelector.java new file mode 100644 index 0000000000..42245e50b1 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/ResultSetType.java b/src/main/java/org/alfresco/service/cmr/search/ResultSetType.java new file mode 100644 index 0000000000..a9e793f0b1 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/SearchParameters.java b/src/main/java/org/alfresco/service/cmr/search/SearchParameters.java new file mode 100644 index 0000000000..e81e51c2d8 --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/search/SearchParameters.java @@ -0,0 +1,1453 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 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; + + /** + * 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.searchTerm = this.searchTerm; + sp.spellCheck = this.spellCheck; + 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; + } + + /** + * Set the query language. + * + * @param language - + * the query language. + */ + public void setLanguage(String language) + { + this.language = language; + } + + 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); + } + + /** + * 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 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; + } + + /** + * @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 + ((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 (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() + { + 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(this.filterQueries).append(", filterQueries=").append(this.filterQueries) + .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(", spellCheck=").append(this.spellCheck).append("]"); + return builder.toString(); + } + + + public enum FieldFacetSort + { + COUNT, INDEX; + } + + public enum FieldFacetMethod + { + ENUM, FC; + } + + public static class FieldFacet + { + String field; + 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; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (countDocsMissingFacetField ? 1231 : 1237); + result = prime * result + enumMethodCacheMinDF; + result = prime * result + ((field == null) ? 0 : field.hashCode()); + result = prime * result + ((limitOrNull == null) ? 0 : limitOrNull.hashCode()); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + result = prime * result + minCount; + result = prime * result + offset; + result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); + result = prime * result + ((sort == null) ? 0 : sort.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; + FieldFacet other = (FieldFacet) obj; + if (countDocsMissingFacetField != other.countDocsMissingFacetField) + return false; + if (enumMethodCacheMinDF != other.enumMethodCacheMinDF) + return false; + if (field == null) + { + if (other.field != null) + return false; + } + else if (!field.equals(other.field)) + return false; + if (limitOrNull == null) + { + if (other.limitOrNull != null) + return false; + } + else if (!limitOrNull.equals(other.limitOrNull)) + return false; + if (method != other.method) + return false; + if (minCount != other.minCount) + return false; + if (offset != other.offset) + return false; + if (prefix == null) + { + if (other.prefix != null) + return false; + } + else if (!prefix.equals(other.prefix)) + return false; + if (sort != other.sort) + return false; + return true; + } + + + } + + /** + * @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); + } + +} diff --git a/src/main/java/org/alfresco/service/cmr/search/SearchService.java b/src/main/java/org/alfresco/service/cmr/search/SearchService.java new file mode 100644 index 0000000000..abfab610e3 --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/search/SearchService.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.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"; + + /** + * 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/src/main/java/org/alfresco/service/cmr/search/SpellCheckResult.java b/src/main/java/org/alfresco/service/cmr/search/SpellCheckResult.java new file mode 100644 index 0000000000..ee05ec9d15 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/StatsParameters.java b/src/main/java/org/alfresco/service/cmr/search/StatsParameters.java new file mode 100644 index 0000000000..c4d91b5c81 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/StatsProcessor.java b/src/main/java/org/alfresco/service/cmr/search/StatsProcessor.java new file mode 100644 index 0000000000..dc3c378882 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/StatsProcessorUsingMap.java b/src/main/java/org/alfresco/service/cmr/search/StatsProcessorUsingMap.java new file mode 100644 index 0000000000..e299836bd7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/StatsResultSet.java b/src/main/java/org/alfresco/service/cmr/search/StatsResultSet.java new file mode 100644 index 0000000000..f121e95cc3 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/StatsResultStat.java b/src/main/java/org/alfresco/service/cmr/search/StatsResultStat.java new file mode 100644 index 0000000000..13bc36feb7 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/search/StatsService.java b/src/main/java/org/alfresco/service/cmr/search/StatsService.java new file mode 100644 index 0000000000..798c26be42 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/security/AccessPermission.java b/src/main/java/org/alfresco/service/cmr/security/AccessPermission.java new file mode 100644 index 0000000000..e6d710587f --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/security/AccessStatus.java b/src/main/java/org/alfresco/service/cmr/security/AccessStatus.java new file mode 100644 index 0000000000..78e36bff1f --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/security/AuthorityType.java b/src/main/java/org/alfresco/service/cmr/security/AuthorityType.java new file mode 100644 index 0000000000..00b2e8880c --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/security/PermissionContext.java b/src/main/java/org/alfresco/service/cmr/security/PermissionContext.java new file mode 100644 index 0000000000..884fb80179 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/cmr/security/PermissionService.java b/src/main/java/org/alfresco/service/cmr/security/PermissionService.java new file mode 100644 index 0000000000..7e74dcd67d --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/DynamicNamespacePrefixResolver.java b/src/main/java/org/alfresco/service/namespace/DynamicNamespacePrefixResolver.java new file mode 100644 index 0000000000..279ca261ee --- /dev/null +++ b/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.keySet()); + return uris; + } +} diff --git a/src/main/java/org/alfresco/service/namespace/InvalidQNameException.java b/src/main/java/org/alfresco/service/namespace/InvalidQNameException.java new file mode 100644 index 0000000000..b61026ff51 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/NamespaceException.java b/src/main/java/org/alfresco/service/namespace/NamespaceException.java new file mode 100644 index 0000000000..4280094578 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolver.java b/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolver.java new file mode 100644 index 0000000000..17f3ddae6c --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolverProvider.java b/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolverProvider.java new file mode 100644 index 0000000000..3a596b79e8 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/NamespaceService.java b/src/main/java/org/alfresco/service/namespace/NamespaceService.java new file mode 100644 index 0000000000..2e11398706 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/NamespaceServiceMemoryImpl.java b/src/main/java/org/alfresco/service/namespace/NamespaceServiceMemoryImpl.java new file mode 100644 index 0000000000..10eb7478e6 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/QName.java b/src/main/java/org/alfresco/service/namespace/QName.java new file mode 100644 index 0000000000..fda96c63c1 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/QNameCache.java b/src/main/java/org/alfresco/service/namespace/QNameCache.java new file mode 100644 index 0000000000..7027064d76 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/QNameMap.java b/src/main/java/org/alfresco/service/namespace/QNameMap.java new file mode 100644 index 0000000000..747dd186b1 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/QNamePattern.java b/src/main/java/org/alfresco/service/namespace/QNamePattern.java new file mode 100644 index 0000000000..405a94d882 --- /dev/null +++ b/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/src/main/java/org/alfresco/service/namespace/RegexQNamePattern.java b/src/main/java/org/alfresco/service/namespace/RegexQNamePattern.java new file mode 100644 index 0000000000..d3e04633e4 --- /dev/null +++ b/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/src/main/java/org/alfresco/util/BaseApplicationContextHelper.java b/src/main/java/org/alfresco/util/BaseApplicationContextHelper.java new file mode 100644 index 0000000000..a6dcb44609 --- /dev/null +++ b/src/main/java/org/alfresco/util/BaseApplicationContextHelper.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.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 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; + +import sun.misc.CompoundEnumeration; + +/** + * 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; + } + } +} diff --git a/src/main/java/org/alfresco/util/DataModelTestApplicationContextHelper.java b/src/main/java/org/alfresco/util/DataModelTestApplicationContextHelper.java new file mode 100644 index 0000000000..4891dbe5aa --- /dev/null +++ b/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/src/main/java/org/alfresco/util/ISO9075.java b/src/main/java/org/alfresco/util/ISO9075.java new file mode 100644 index 0000000000..5a281e1d73 --- /dev/null +++ b/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/src/main/java/org/alfresco/util/LazyClassPathXmlApplicationContext.java b/src/main/java/org/alfresco/util/LazyClassPathXmlApplicationContext.java new file mode 100644 index 0000000000..343e4c0693 --- /dev/null +++ b/src/main/java/org/alfresco/util/LazyClassPathXmlApplicationContext.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.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 createHelper( + XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) { + BeanDefinitionParserDelegate helper = super.createHelper(readerContext, root, parentDelegate); + helper.getDefaults().setLazyInit("true"); + return helper; + } + } +} diff --git a/src/main/java/org/alfresco/util/NoAutoStartClassPathXmlApplicationContext.java b/src/main/java/org/alfresco/util/NoAutoStartClassPathXmlApplicationContext.java new file mode 100644 index 0000000000..059742e040 --- /dev/null +++ b/src/main/java/org/alfresco/util/NoAutoStartClassPathXmlApplicationContext.java @@ -0,0 +1,99 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 createHelper( + 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/src/main/java/org/alfresco/util/NumericEncoder.java b/src/main/java/org/alfresco/util/NumericEncoder.java new file mode 100644 index 0000000000..113a3bca18 --- /dev/null +++ b/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/src/main/java/org/alfresco/util/SearchLanguageConversion.java b/src/main/java/org/alfresco/util/SearchLanguageConversion.java new file mode 100644 index 0000000000..44d28971be --- /dev/null +++ b/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/src/main/java/org/alfresco/util/WebApplicationContextLoader.java b/src/main/java/org/alfresco/util/WebApplicationContextLoader.java new file mode 100644 index 0000000000..ff882adb3a --- /dev/null +++ b/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/src/main/java/org/apache/tika/mime/custom-mimetypes.xml b/src/main/java/org/apache/tika/mime/custom-mimetypes.xml new file mode 100644 index 0000000000..4b3df3f6f3 --- /dev/null +++ b/src/main/java/org/apache/tika/mime/custom-mimetypes.xml @@ -0,0 +1,28 @@ + + + + + + + <_comment>Alfresco Content Package + + + + diff --git a/src/main/resources/alfresco/data-model-stand-alone-context.xml b/src/main/resources/alfresco/data-model-stand-alone-context.xml new file mode 100644 index 0000000000..d03b12e724 --- /dev/null +++ b/src/main/resources/alfresco/data-model-stand-alone-context.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + 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/src/main/resources/alfresco/messages/dictionary-messages.properties b/src/main/resources/alfresco/messages/dictionary-messages.properties new file mode 100644 index 0000000000..929016b506 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model.properties b/src/main/resources/alfresco/messages/dictionary-model.properties new file mode 100644 index 0000000000..f9ceae5b4e --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_de.properties b/src/main/resources/alfresco/messages/dictionary-model_de.properties new file mode 100755 index 0000000000..c5c50f03c5 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_es.properties b/src/main/resources/alfresco/messages/dictionary-model_es.properties new file mode 100755 index 0000000000..075d713a83 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_fr.properties b/src/main/resources/alfresco/messages/dictionary-model_fr.properties new file mode 100755 index 0000000000..f143b99c2f --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_it.properties b/src/main/resources/alfresco/messages/dictionary-model_it.properties new file mode 100755 index 0000000000..a27c70302b --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_ja.properties b/src/main/resources/alfresco/messages/dictionary-model_ja.properties new file mode 100755 index 0000000000..f8322fa94b --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_nb.properties b/src/main/resources/alfresco/messages/dictionary-model_nb.properties new file mode 100755 index 0000000000..7139a64ae5 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_nl.properties b/src/main/resources/alfresco/messages/dictionary-model_nl.properties new file mode 100755 index 0000000000..08e61a6f44 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_pt_BR.properties b/src/main/resources/alfresco/messages/dictionary-model_pt_BR.properties new file mode 100644 index 0000000000..90111a6018 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_ru.properties b/src/main/resources/alfresco/messages/dictionary-model_ru.properties new file mode 100755 index 0000000000..c89d6280d0 --- /dev/null +++ b/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/src/main/resources/alfresco/messages/dictionary-model_zh_CN.properties b/src/main/resources/alfresco/messages/dictionary-model_zh_CN.properties new file mode 100755 index 0000000000..34ab9b1f0a --- /dev/null +++ b/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/src/main/resources/alfresco/mimetype/mimetype-map-openoffice.xml b/src/main/resources/alfresco/mimetype/mimetype-map-openoffice.xml new file mode 100644 index 0000000000..f610eec30d --- /dev/null +++ b/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/src/main/resources/alfresco/mimetype/mimetype-map.xml b/src/main/resources/alfresco/mimetype/mimetype-map.xml new file mode 100644 index 0000000000..b2a7a663f5 --- /dev/null +++ b/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/src/main/resources/alfresco/model/cmisModel.xml b/src/main/resources/alfresco/model/cmisModel.xml new file mode 100644 index 0000000000..20d02b74f6 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers.properties new file mode 100644 index 0000000000..94a1f655c2 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties new file mode 100644 index 0000000000..a808ef4aba --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties new file mode 100644 index 0000000000..f24e343726 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties new file mode 100644 index 0000000000..01b1086291 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties new file mode 100644 index 0000000000..3be1f75e67 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties new file mode 100644 index 0000000000..9b92c0b6d0 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties new file mode 100644 index 0000000000..43da2753ec --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties new file mode 100644 index 0000000000..eb48e159d9 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties new file mode 100644 index 0000000000..0532029d20 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties new file mode 100644 index 0000000000..341d8716fd --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties new file mode 100644 index 0000000000..e3adf49bba --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties new file mode 100644 index 0000000000..e3adf49bba --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties new file mode 100644 index 0000000000..d630049498 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties new file mode 100644 index 0000000000..32f779db95 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties new file mode 100644 index 0000000000..941719040c --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties new file mode 100644 index 0000000000..d9fcc7a929 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties new file mode 100644 index 0000000000..2db4278326 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties new file mode 100644 index 0000000000..81e2cb4c22 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties new file mode 100644 index 0000000000..aa0400a3d8 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties b/src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties new file mode 100644 index 0000000000..55cf861ae5 --- /dev/null +++ b/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/src/main/resources/alfresco/model/dictionaryModel.xml b/src/main/resources/alfresco/model/dictionaryModel.xml new file mode 100644 index 0000000000..fe31d97726 --- /dev/null +++ b/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/src/test/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryServiceTest.java b/src/test/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryServiceTest.java new file mode 100644 index 0000000000..04ea570136 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/cache/SimpleCacheTestBase.java b/src/test/java/org/alfresco/repo/cache/SimpleCacheTestBase.java new file mode 100644 index 0000000000..4988972443 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/content/DataModelContentTestSuite.java b/src/test/java/org/alfresco/repo/content/DataModelContentTestSuite.java new file mode 100644 index 0000000000..da87933778 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/content/MimetypeMapTest.java b/src/test/java/org/alfresco/repo/content/MimetypeMapTest.java new file mode 100644 index 0000000000..9da228117a --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/MimetypeMapTest.java @@ -0,0 +1,583 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.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; + +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 junit.framework.TestCase; + +/** + * @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 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 = MimetypeMap.MIMETYPE_HTML; + + public DummyContentReader() + { + super(); + } + + public DummyContentReader(String mimetype) + { + this.mimetype = mimetype; + } + + @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("@@/Y".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/src/test/java/org/alfresco/repo/content/encoding/CharsetFinderTest.java b/src/test/java/org/alfresco/repo/content/encoding/CharsetFinderTest.java new file mode 100644 index 0000000000..0edade757f --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/encoding/CharsetFinderTest.java @@ -0,0 +1,121 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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 + } +} diff --git a/src/test/java/org/alfresco/repo/dictionary/AbstractModelTest.java b/src/test/java/org/alfresco/repo/dictionary/AbstractModelTest.java new file mode 100644 index 0000000000..3b81760c58 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/dictionary/DictionaryComponentTest.java b/src/test/java/org/alfresco/repo/dictionary/DictionaryComponentTest.java new file mode 100644 index 0000000000..6e11619e79 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java b/src/test/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java new file mode 100644 index 0000000000..5ba4728665 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/dictionary/DiffModelTest.java b/src/test/java/org/alfresco/repo/dictionary/DiffModelTest.java new file mode 100644 index 0000000000..ca5308fc73 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java b/src/test/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java new file mode 100644 index 0000000000..e1528d428e --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/index/ShardMethodEnumTest.java b/src/test/java/org/alfresco/repo/index/ShardMethodEnumTest.java new file mode 100644 index 0000000000..8c368913a6 --- /dev/null +++ b/src/test/java/org/alfresco/repo/index/ShardMethodEnumTest.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.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 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 testTypeDateTimeStamp() + { + Assert.assertEquals(ShardMethodEnum.DATE, ShardMethodEnum.getShardMethod("DATE")); + } + @Test + public void testTypeDateYear() + { + Assert.assertEquals(ShardMethodEnum.DATE_YEAR, ShardMethodEnum.getShardMethod("DATE_YEAR")); + } + @Test + public void testTypeDateMonth() + { + Assert.assertEquals(ShardMethodEnum.DATE_MONTH, ShardMethodEnum.getShardMethod("DATE_MONTH")); + } + @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/src/test/java/org/alfresco/repo/search/impl/parsers/CMISTest.java b/src/test/java/org/alfresco/repo/search/impl/parsers/CMISTest.java new file mode 100644 index 0000000000..e423b10af2 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSTest.java b/src/test/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSTest.java new file mode 100644 index 0000000000..249f488eeb --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/search/impl/parsers/FTSTest.java b/src/test/java/org/alfresco/repo/search/impl/parsers/FTSTest.java new file mode 100644 index 0000000000..48d1fc6657 --- /dev/null +++ b/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/src/test/java/org/alfresco/repo/search/impl/parsers/gUnitExecutor.java b/src/test/java/org/alfresco/repo/search/impl/parsers/gUnitExecutor.java new file mode 100644 index 0000000000..75ff2b38b8 --- /dev/null +++ b/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/src/test/java/org/alfresco/service/cmr/repository/MLTextTest.java b/src/test/java/org/alfresco/service/cmr/repository/MLTextTest.java new file mode 100644 index 0000000000..d839848e86 --- /dev/null +++ b/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/src/test/java/org/alfresco/service/cmr/repository/NodeRefTest.java b/src/test/java/org/alfresco/service/cmr/repository/NodeRefTest.java new file mode 100644 index 0000000000..223a65a8f1 --- /dev/null +++ b/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/src/test/java/org/alfresco/service/cmr/repository/PathTest.java b/src/test/java/org/alfresco/service/cmr/repository/PathTest.java new file mode 100644 index 0000000000..2ff901b10e --- /dev/null +++ b/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/src/test/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java b/src/test/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java new file mode 100644 index 0000000000..e2ba16f68b --- /dev/null +++ b/src/test/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java @@ -0,0 +1,350 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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.Locale; + +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")); + // 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/src/test/java/org/alfresco/service/cmr/search/StatsProcessorTest.java b/src/test/java/org/alfresco/service/cmr/search/StatsProcessorTest.java new file mode 100644 index 0000000000..39f8e3d6ae --- /dev/null +++ b/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/src/test/java/org/alfresco/service/namespace/DynamicNameSpaceResolverTest.java b/src/test/java/org/alfresco/service/namespace/DynamicNameSpaceResolverTest.java new file mode 100644 index 0000000000..354cbd9259 --- /dev/null +++ b/src/test/java/org/alfresco/service/namespace/DynamicNameSpaceResolverTest.java @@ -0,0 +1,121 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more 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; + +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()); + assertNotNull(dnpr.getPrefixes()); + assertNotNull(dnpr.getURIs()); + assertNotNull(new DynamicNamespacePrefixResolver()); + } + +} diff --git a/src/test/java/org/alfresco/service/namespace/QNamePatternTest.java b/src/test/java/org/alfresco/service/namespace/QNamePatternTest.java new file mode 100644 index 0000000000..be8796c0a0 --- /dev/null +++ b/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/src/test/java/org/alfresco/service/namespace/QNameTest.java b/src/test/java/org/alfresco/service/namespace/QNameTest.java new file mode 100644 index 0000000000..cfd7101bb9 --- /dev/null +++ b/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/src/test/java/org/alfresco/util/ISO9075Test.java b/src/test/java/org/alfresco/util/ISO9075Test.java new file mode 100644 index 0000000000..87994feed2 --- /dev/null +++ b/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/src/test/java/org/alfresco/util/NumericEncodingTest.java b/src/test/java/org/alfresco/util/NumericEncodingTest.java new file mode 100644 index 0000000000..e4e3c5d88b --- /dev/null +++ b/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/src/test/java/org/alfresco/util/SearchLanguageConversionTest.java b/src/test/java/org/alfresco/util/SearchLanguageConversionTest.java new file mode 100644 index 0000000000..98c239a898 --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/commonpropertynschild_model.xml b/src/test/resources/org/alfresco/repo/dictionary/commonpropertynschild_model.xml new file mode 100644 index 0000000000..485e0aa6bf --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/commonpropertynsparent_model.xml b/src/test/resources/org/alfresco/repo/dictionary/commonpropertynsparent_model.xml new file mode 100644 index 0000000000..773882a930 --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.properties b/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.properties new file mode 100644 index 0000000000..319799ac26 --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.xml b/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.xml new file mode 100644 index 0000000000..5f317f446d --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.properties b/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.properties new file mode 100644 index 0000000000..7ff0b4b99c --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.xml b/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.xml new file mode 100644 index 0000000000..10c6a08450 --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/modelCircularTypes.xml b/src/test/resources/org/alfresco/repo/dictionary/modelCircularTypes.xml new file mode 100644 index 0000000000..41fe6f698b --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/dictionary/nstest_model.xml b/src/test/resources/org/alfresco/repo/dictionary/nstest_model.xml new file mode 100644 index 0000000000..b676d40846 --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_fts_test.gunit b/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_fts_test.gunit new file mode 100644 index 0000000000..3d05ee6f05 --- /dev/null +++ b/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/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_test.gunit b/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_test.gunit new file mode 100644 index 0000000000..0a9089d1ca --- /dev/null +++ b/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_test.gunit @@ -0,0 +1,556 @@ +/** 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 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/src/test/resources/org/alfresco/repo/search/impl/parsers/fts_test.gunit b/src/test/resources/org/alfresco/repo/search/impl/parsers/fts_test.gunit new file mode 100644 index 0000000000..90d1f43223 --- /dev/null +++ b/src/test/resources/org/alfresco/repo/search/impl/parsers/fts_test.gunit @@ -0,0 +1,496 @@ +/** 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)))))" + + +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)))))))" + +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 +"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 + + + +