001/* 002 * (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.query.sql; 020 021import java.time.ZoneOffset; 022import java.time.ZonedDateTime; 023import java.time.format.DateTimeParseException; 024 025import org.nuxeo.common.utils.PeriodAndDuration; 026import org.nuxeo.runtime.api.Framework; 027 028/** 029 * This defines the constants for NXQL queries. 030 * 031 * @author Florent Guillaume 032 */ 033public class NXQL { 034 035 /** 036 * Property containing the test value of the current date for {@link #nowPlusPeriodAndDuration}. 037 * <p> 038 * Only for tests, not a public API. 039 * 040 * @since 11.1 041 */ 042 public static final String TEST_NXQL_NOW = "test.nxql.now"; 043 044 // constant utility class 045 private NXQL() { 046 } 047 048 /** The NXQL query type. */ 049 public static final String NXQL = "NXQL"; 050 051 public static final String ECM_PREFIX = "ecm:"; 052 053 public static final String ECM_UUID = "ecm:uuid"; 054 055 public static final String ECM_PATH = "ecm:path"; 056 057 public static final String ECM_NAME = "ecm:name"; 058 059 public static final String ECM_POS = "ecm:pos"; 060 061 public static final String ECM_PARENTID = "ecm:parentId"; 062 063 public static final String ECM_MIXINTYPE = "ecm:mixinType"; 064 065 public static final String ECM_PRIMARYTYPE = "ecm:primaryType"; 066 067 public static final String ECM_ISPROXY = "ecm:isProxy"; 068 069 public static final String ECM_ISVERSION = "ecm:isVersion"; 070 071 /** 072 * @since 5.7.3 073 */ 074 public static final String ECM_ISVERSION_OLD = "ecm:isCheckedInVersion"; 075 076 public static final String ECM_LIFECYCLESTATE = "ecm:currentLifeCycleState"; 077 078 public static final String ECM_VERSIONLABEL = "ecm:versionLabel"; 079 080 public static final String ECM_FULLTEXT = "ecm:fulltext"; 081 082 public static final String ECM_FULLTEXT_JOBID = "ecm:fulltextJobId"; 083 084 /** 085 * @since 6.0 086 */ 087 public static final String ECM_FULLTEXT_SCORE = "ecm:fulltextScore"; 088 089 /** 090 * @since 5.4.2 091 */ 092 public static final String ECM_LOCK_OWNER = "ecm:lockOwner"; 093 094 /** 095 * @since 5.4.2 096 */ 097 public static final String ECM_LOCK_CREATED = "ecm:lockCreated"; 098 099 /** 100 * @since 5.7 101 */ 102 public static final String ECM_TAG = "ecm:tag"; 103 104 /** 105 * @since 5.7 106 */ 107 public static final String ECM_PROXY_TARGETID = "ecm:proxyTargetId"; 108 109 /** 110 * @since 5.7 111 */ 112 public static final String ECM_PROXY_VERSIONABLEID = "ecm:proxyVersionableId"; 113 114 /** 115 * @since 5.7.3 116 */ 117 public static final String ECM_ISCHECKEDIN = "ecm:isCheckedIn"; 118 119 /** 120 * @since 5.7.3 121 */ 122 public static final String ECM_ISLATESTVERSION = "ecm:isLatestVersion"; 123 124 /** 125 * @since 5.7.3 126 */ 127 public static final String ECM_ISLATESTMAJORVERSION = "ecm:isLatestMajorVersion"; 128 129 /** 130 * @since 5.7.3 131 */ 132 public static final String ECM_VERSIONCREATED = "ecm:versionCreated"; 133 134 /** 135 * @since 5.7.3 136 */ 137 public static final String ECM_VERSIONDESCRIPTION = "ecm:versionDescription"; 138 139 /** 140 * @since 5.7.3 141 */ 142 public static final String ECM_VERSION_VERSIONABLEID = "ecm:versionVersionableId"; 143 144 /** 145 * @since 6.0 146 */ 147 public static final String ECM_ANCESTORID = "ecm:ancestorId"; 148 149 /** 150 * @since 6.0-HF06, 7.2 151 */ 152 public static final String ECM_ACL = "ecm:acl"; 153 154 /** 155 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /principal} 156 * 157 * @since 6.0-HF06, 7.2 158 */ 159 public static final String ECM_ACL_PRINCIPAL = "principal"; 160 161 /** 162 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /permission} 163 * 164 * @since 6.0-HF06, 7.2 165 */ 166 public static final String ECM_ACL_PERMISSION = "permission"; 167 168 /** 169 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /grant} 170 * 171 * @since 6.0-HF06, 7.2 172 */ 173 public static final String ECM_ACL_GRANT = "grant"; 174 175 /** 176 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /name} 177 * 178 * @since 6.0-HF06, 7.2 179 */ 180 public static final String ECM_ACL_NAME = "name"; 181 182 /** 183 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /pos} 184 * 185 * @since 6.0-HF06, 7.2 186 */ 187 public static final String ECM_ACL_POS = "pos"; 188 189 /** 190 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /creator} 191 * 192 * @since 7.4 193 */ 194 public static final String ECM_ACL_CREATOR = "creator"; 195 196 /** 197 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /begin} 198 * 199 * @since 7.4 200 */ 201 public static final String ECM_ACL_BEGIN = "begin"; 202 203 /** 204 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /end} 205 * 206 * @since 7.4 207 */ 208 public static final String ECM_ACL_END = "end"; 209 210 /** 211 * Suffix for ecm:acl, like in {@code ecm:acl/}{@code *}{@code /status} 212 * 213 * @since 7.4 214 */ 215 public static final String ECM_ACL_STATUS = "status"; 216 217 /** 218 * @since 10.1 219 */ 220 public static final String ECM_ISTRASHED = "ecm:isTrashed"; 221 222 /** @since 11.1 */ 223 public static final String ECM_ISRECORD = "ecm:isRecord"; 224 225 /** @since 11.1 */ 226 public static final String ECM_RETAINUNTIL = "ecm:retainUntil"; 227 228 /** @since 11.1 */ 229 public static final String ECM_HASLEGALHOLD = "ecm:hasLegalHold"; 230 231 /** 232 * The function returning the current datetime. It can optionally have as an argument a duration that will be added 233 * to the current datetime, expressed as a ISO 8601 period. 234 * <p> 235 * See {@link PeriodAndDuration#parse} for the exact format. 236 * 237 * @see PeriodAndDuration#parse 238 * @since 11.1 239 */ 240 public static final String NOW_FUNCTION = "NOW"; 241 242 /** 243 * Escapes a string into a single-quoted string for NXQL. 244 * <p> 245 * Any single quote or backslash characters are escaped with a backslash. 246 * 247 * @param s the string to escape 248 * @return the escaped string 249 * @since 5.7, 5.6.0-HF08 250 */ 251 public static String escapeString(String s) { 252 return "'" + escapeStringInner(s) + "'"; 253 } 254 255 /** 256 * Escapes a string (assumed to be single quoted) for NXQL. 257 * <p> 258 * Any single quote or backslash characters are escaped with a backslash. 259 * 260 * @param s the string to escape 261 * @return the escaped string, without external quotes 262 * @since 5.7, 5.6.0-HF08 263 */ 264 public static String escapeStringInner(String s) { 265 // backslash -> backslash backslash 266 // quote -> backslash quote 267 // newline -> backslash n 268 return s.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'").replaceAll("\n", "\\\\n"); 269 } 270 271 /** 272 * Returns the current dateTime to which the period and duration (if present) has been added. 273 * 274 * @param periodAndDurationText the period and duration as text, or {@code null} 275 * @return the current dateTime to which the period and duration has been added 276 * @throws IllegalArgumentException if the period and duration cannot be parsed 277 * @since 11.1 278 */ 279 // also used by NxqlQueryConverter 280 public static ZonedDateTime nowPlusPeriodAndDuration(String periodAndDurationText) { 281 ZonedDateTime now; 282 if (Framework.getProperty(TEST_NXQL_NOW) != null) { 283 now = ZonedDateTime.parse(Framework.getProperty(TEST_NXQL_NOW)); 284 } else { 285 now = ZonedDateTime.now(ZoneOffset.UTC); 286 } 287 if (periodAndDurationText == null) { 288 return now; 289 } else { 290 PeriodAndDuration pd; 291 try { 292 pd = PeriodAndDuration.parse(periodAndDurationText); 293 } catch (DateTimeParseException e) { 294 throw new IllegalArgumentException("Invalid period: " + periodAndDurationText, e); 295 } 296 return now.plus(pd); 297 } 298 } 299 300}