Compare commits
No commits in common. "61e969e628457563bd95ae9288fce2c5cb744dcf" and "74d51599b1d3df94f0eab2f58fb9f7a5ae0c16c7" have entirely different histories.
61e969e628
...
74d51599b1
209 changed files with 2979 additions and 17574 deletions
12
.travis.yml
Normal file
12
.travis.yml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
language: java
|
||||||
|
sudo: required
|
||||||
|
jdk:
|
||||||
|
- oraclejdk8
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.m2
|
||||||
|
after_success:
|
||||||
|
- ./gradlew sonarqube -Dsonar.host.url=https://sonarqube.com -Dsonar.login=$SONAR_TOKEN
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
secure: n1Ai4q/yMLn/Pg5pA4lTavoJoe7mQYB1PSKnZAqwbgyla94ySzK6iyBCBiNs/foMPisB/x+DHvmUXTsjvquw9Ay48ZITCV3xhcWzD0eZM2TMoG19CpRAEe8L8LNuYiti9k89ijDdUGZ5ifsvQNTGNHksouayAuApC3PrTUejJfR6SYrp1ZsQTbsMlr+4XU3p7QknK5rGgOwATIMP28F+bVnB05WJtlJA3b0SeucCurn3wJ4FGBQXRYmdlT7bQhNE4QgZM1VzcUFD/K0TBxzzq/otb/lNRSifyoekktDmJwQnaT9uQ4R8R6KdQ2Kb38Rvgjur+TKm5i1G8qS2+6LnIxQJG1aw3JvKK6W0wWCgnAVVRrXaCLday9NuY59tuh1mfjQ10UcsMNKcTdcKEMrLow506wSETcXc7L/LEnneWQyJJeV4vhPqR7KJfsBbeqgz3yIfsCn1GZVWFlfegzYCN52YTl0Y0uRD2Z+TnzQu+Bf4DzaWXLge1rz31xkhyeNNspub4h024+XqBjcMm6M9mlMzmmK8t2DIwPy/BlQbFBUyhrxziuR/5/2NEDPyHltvWkRb4AUIa25WJqkV0gTBegbMadZ9DyOo6Ea7aoVFBae2WGR08F1kzABsWrd1S7UJmWxW35iyMEtoAIayXphIK98qO5aCutwZ+3iOQazxbAs=
|
|
@ -7,8 +7,6 @@ org.xbib.time is based upon the following software:
|
||||||
|
|
||||||
- prettytime https://github.com/ocpsoft/prettytime (Apache 2.0)
|
- prettytime https://github.com/ocpsoft/prettytime (Apache 2.0)
|
||||||
|
|
||||||
- cron expression https://github.com/anderswisch/cron-expression/ (MIT License)
|
|
||||||
|
|
||||||
with improvements by Jörg Prante including
|
with improvements by Jörg Prante including
|
||||||
|
|
||||||
- converted to Java 8 java.time API
|
- converted to Java 8 java.time API
|
||||||
|
@ -18,5 +16,3 @@ with improvements by Jörg Prante including
|
||||||
- refactoring classes
|
- refactoring classes
|
||||||
|
|
||||||
- rewritten code to simplify and ease development
|
- rewritten code to simplify and ease development
|
||||||
|
|
||||||
- added nextExecution() method to cron expression and scheduling via Callable
|
|
14
README.adoc
Normal file
14
README.adoc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# xbib Time
|
||||||
|
|
||||||
|
image:https://api.travis-ci.org/xbib/time.svg[title="Build status", link="https://travis-ci.org/xbib/time/"]
|
||||||
|
image:https://img.shields.io/sonar/http/nemo.sonarqube.com/org.xbib%3Atime/coverage.svg?style=flat-square[title="Coverage", link="https://sonarqube.com/dashboard/index?id=org.xbib%3Atime"]
|
||||||
|
image:https://maven-badges.herokuapp.com/maven-central/org.xbib/time/badge.svg[title="Maven Central", link="http://search.maven.org/#search%7Cga%7C1%7Cxbib%20time"]
|
||||||
|
image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[title="Apache License 2.0", link="https://opensource.org/licenses/Apache-2.0"]
|
||||||
|
|
||||||
|
This is a bundle of time utilities for Java 8 Time API. It consists of
|
||||||
|
|
||||||
|
- Chronic: parsing natural language to compute time spans (from https://github.com/samtingleff/jchronic)
|
||||||
|
- Pretty: pretty printing time durations (from https://github.com/ocpsoft/prettytime)
|
||||||
|
- Format: format time descriptions (from https://github.com/JodaOrg/joda-time)
|
||||||
|
|
||||||
|
This project has no dependencies.
|
|
@ -1,9 +0,0 @@
|
||||||
# xbib Time
|
|
||||||
|
|
||||||
This is a bundle of time utilities for Java 8 Time API. It consists of
|
|
||||||
|
|
||||||
- Chronic: parsing natural language to compute time spans (from https://github.com/samtingleff/jchronic)
|
|
||||||
- Pretty: pretty printing time durations (from https://github.com/ocpsoft/prettytime)
|
|
||||||
- Format: format time descriptions (from https://github.com/JodaOrg/joda-time)
|
|
||||||
|
|
||||||
This project has no dependencies.
|
|
98
build.gradle
98
build.gradle
|
@ -1,40 +1,76 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'maven-publish'
|
id "org.sonarqube" version "2.2"
|
||||||
id 'signing'
|
id 'org.ajoberstar.github-pages' version '1.6.0-rc.1'
|
||||||
id "io.github.gradle-nexus.publish-plugin" version "2.0.0-rc-1"
|
id "org.xbib.gradle.plugin.jbake" version "1.2.1"
|
||||||
id "org.xbib.gradle.plugin.asciidoctor" version "3.0.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper {
|
printf "Host: %s\nOS: %s %s %s\nJVM: %s %s %s %s\nGroovy: %s\nGradle: %s\n" +
|
||||||
gradleVersion = libs.versions.gradle.get()
|
"Build: group: ${project.group} name: ${project.name} version: ${project.version}\n",
|
||||||
distributionType = Wrapper.DistributionType.BIN
|
InetAddress.getLocalHost(),
|
||||||
}
|
System.getProperty("os.name"),
|
||||||
|
System.getProperty("os.arch"),
|
||||||
|
System.getProperty("os.version"),
|
||||||
|
System.getProperty("java.version"),
|
||||||
|
System.getProperty("java.vm.version"),
|
||||||
|
System.getProperty("java.vm.vendor"),
|
||||||
|
System.getProperty("java.vm.name"),
|
||||||
|
GroovySystem.getVersion(),
|
||||||
|
gradle.gradleVersion
|
||||||
|
|
||||||
ext {
|
apply plugin: 'java'
|
||||||
user = 'joerg'
|
apply plugin: 'maven'
|
||||||
name = 'time'
|
apply plugin: 'signing'
|
||||||
description = 'A bundle of Chronic, Prettytime, and org.joda.time.format optimized for Java 8 Time API'
|
apply plugin: 'findbugs'
|
||||||
inceptionYear = '2016'
|
apply plugin: 'pmd'
|
||||||
url = 'https://xbib.org/' + user + '/' + name
|
apply plugin: 'checkstyle'
|
||||||
scmUrl = 'https://xbib.org/' + user + '/' + name
|
apply plugin: "jacoco"
|
||||||
scmConnection = 'scm:git:git://xbib.org/' + user + '/' + name + '.git'
|
apply plugin: 'org.ajoberstar.github-pages'
|
||||||
scmDeveloperConnection = 'scm:git:ssh://forgejo@xbib.org:' + user + '/' + name + '.git'
|
|
||||||
issueManagementSystem = 'Github'
|
|
||||||
issueManagementUrl = ext.scmUrl + '/issues'
|
|
||||||
licenseName = 'The Apache License, Version 2.0'
|
|
||||||
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
configurations {
|
||||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
wagon
|
||||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
provided
|
||||||
apply from: rootProject.file('gradle/publish/maven.gradle')
|
testCompile.extendsFrom(provided)
|
||||||
apply from: rootProject.file('gradle/publish/forgejo.gradle')
|
}
|
||||||
apply from: rootProject.file('gradle/publish/sonatype.gradle')
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation testLibs.quartz
|
testCompile 'junit:junit:4.12'
|
||||||
testImplementation testLibs.caliper
|
testCompile 'org.apache.logging.log4j:log4j-core:2.7'
|
||||||
testImplementation testLibs.guava
|
testCompile 'org.apache.logging.log4j:log4j-jul:2.7'
|
||||||
|
wagon 'org.apache.maven.wagon:wagon-ssh-external:2.10'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
|
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs << "-Xlint:all" << "-profile" << "compact2"
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
testLogging {
|
||||||
|
showStandardStreams = false
|
||||||
|
exceptionFormat = 'full'
|
||||||
|
}
|
||||||
|
systemProperty 'java.util.logging.manager', 'org.apache.logging.log4j.jul.LogManager'
|
||||||
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
|
classifier 'sources'
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
}
|
||||||
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
|
classifier 'javadoc'
|
||||||
|
}
|
||||||
|
artifacts {
|
||||||
|
archives sourcesJar, javadocJar
|
||||||
|
}
|
||||||
|
if (project.hasProperty('signing.keyId')) {
|
||||||
|
signing {
|
||||||
|
sign configurations.archives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: 'gradle/ext.gradle'
|
||||||
|
apply from: 'gradle/publish.gradle'
|
||||||
|
apply from: 'gradle/sonarqube.gradle'
|
||||||
|
|
|
@ -9,10 +9,6 @@ page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
|
|
||||||
<module name="Checker">
|
<module name="Checker">
|
||||||
|
|
||||||
<module name="BeforeExecutionExclusionFileFilter">
|
|
||||||
<property name="fileNamePattern" value=".*(Example|Test|module-info)(\$.*)?"/>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="FileTabCharacter">
|
<module name="FileTabCharacter">
|
||||||
<!-- Checks that there are no tab characters in the file.
|
<!-- Checks that there are no tab characters in the file.
|
||||||
-->
|
-->
|
||||||
|
@ -60,19 +56,10 @@ page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
<!-- Checks for out of order import statements. -->
|
<!-- Checks for out of order import statements. -->
|
||||||
|
|
||||||
<property name="severity" value="warning"/>
|
<property name="severity" value="warning"/>
|
||||||
<!-- <property name="tokens" value="IMPORT, STATIC_IMPORT"/> -->
|
<property name="groups" value="com,junit,net,org,java,javax"/>
|
||||||
<property name="separated" value="false"/>
|
<!-- This ensures that static imports go first. -->
|
||||||
<property name="groups" value="*"/>
|
<property name="option" value="top"/>
|
||||||
<!-- <property name="option" value="above"/> -->
|
<property name="tokens" value="STATIC_IMPORT, IMPORT"/>
|
||||||
<property name="sortStaticImportsAlphabetically" value="true"/>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="CustomImportOrder">
|
|
||||||
<!-- <property name="customImportOrderRules" value="THIRD_PARTY_PACKAGE###SPECIAL_IMPORTS###STANDARD_JAVA_PACKAGE###STATIC"/> -->
|
|
||||||
<!-- <property name="specialImportsRegExp" value="^javax\."/> -->
|
|
||||||
<!-- <property name="standardPackageRegExp" value="^java\."/> -->
|
|
||||||
<property name="sortImportsInGroupAlphabetically" value="true"/>
|
|
||||||
<property name="separateLineBetweenGroups" value="false"/>
|
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
@ -84,10 +71,14 @@ page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
<!-- Checks for Javadoc comments. -->
|
<!-- Checks for Javadoc comments. -->
|
||||||
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
|
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
|
||||||
<module name="JavadocMethod">
|
<module name="JavadocMethod">
|
||||||
<property name="accessModifiers" value="protected"/>
|
<property name="scope" value="protected"/>
|
||||||
<property name="severity" value="warning"/>
|
<property name="severity" value="warning"/>
|
||||||
|
<property name="allowMissingJavadoc" value="true"/>
|
||||||
<property name="allowMissingParamTags" value="true"/>
|
<property name="allowMissingParamTags" value="true"/>
|
||||||
<property name="allowMissingReturnTag" value="true"/>
|
<property name="allowMissingReturnTag" value="true"/>
|
||||||
|
<property name="allowMissingThrowsTags" value="true"/>
|
||||||
|
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
||||||
|
<property name="allowUndeclaredRTE" value="true"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<module name="JavadocType">
|
<module name="JavadocType">
|
||||||
|
@ -193,6 +184,21 @@ page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<module name="LineLength">
|
||||||
|
<!-- Checks if a line is too long. -->
|
||||||
|
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="128"/>
|
||||||
|
<property name="severity" value="error"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The default ignore pattern exempts the following elements:
|
||||||
|
- import statements
|
||||||
|
- long URLs inside comments
|
||||||
|
-->
|
||||||
|
|
||||||
|
<property name="ignorePattern"
|
||||||
|
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
||||||
|
default="^(package .*;\s*)|(import .*;\s*)|( *(\*|//).*https?://.*)$"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
<module name="LeftCurly">
|
<module name="LeftCurly">
|
||||||
<!-- Checks for placement of the left curly brace ('{'). -->
|
<!-- Checks for placement of the left curly brace ('{'). -->
|
||||||
|
@ -313,21 +319,5 @@ page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<module name="LineLength">
|
|
||||||
<!-- Checks if a line is too long. -->
|
|
||||||
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="128"/>
|
|
||||||
<property name="severity" value="error"/>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The default ignore pattern exempts the following elements:
|
|
||||||
- import statements
|
|
||||||
- long URLs inside comments
|
|
||||||
-->
|
|
||||||
|
|
||||||
<property name="ignorePattern"
|
|
||||||
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
|
||||||
default="^(package .*;\s*)|(import .*;\s*)|( *(\*|//).*https?://.*)$"/>
|
|
||||||
</module>
|
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = time
|
name = time
|
||||||
version = 4.0.0
|
version = 1.0.0
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
apply plugin: 'java-library'
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(21)
|
|
||||||
}
|
|
||||||
modularity.inferModulePath.set(true)
|
|
||||||
withSourcesJar()
|
|
||||||
withJavadocJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes('Implementation-Version': project.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.fork = true
|
|
||||||
options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
|
|
||||||
options.compilerArgs << '-Xlint:all'
|
|
||||||
options.encoding = 'UTF-8'
|
|
||||||
}
|
|
||||||
|
|
||||||
javadoc {
|
|
||||||
options.addStringOption('Xdoclint:none', '-quiet')
|
|
||||||
options.encoding = 'UTF-8'
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
apply plugin: 'org.xbib.gradle.plugin.asciidoctor'
|
|
||||||
|
|
||||||
asciidoctor {
|
|
||||||
backends 'html5'
|
|
||||||
outputDir = file("${rootProject.projectDir}/docs")
|
|
||||||
separateOutputDirs = false
|
|
||||||
attributes 'source-highlighter': 'coderay',
|
|
||||||
idprefix: '',
|
|
||||||
idseparator: '-',
|
|
||||||
toc: 'left',
|
|
||||||
doctype: 'book',
|
|
||||||
icons: 'font',
|
|
||||||
encoding: 'utf-8',
|
|
||||||
sectlink: true,
|
|
||||||
sectanchors: true,
|
|
||||||
linkattrs: true,
|
|
||||||
imagesdir: 'img',
|
|
||||||
stylesheet: "${projectDir}/src/docs/asciidoc/css/foundation.css"
|
|
||||||
}
|
|
8
gradle/ext.gradle
Normal file
8
gradle/ext.gradle
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
ext {
|
||||||
|
user = 'xbib'
|
||||||
|
projectName = 'time'
|
||||||
|
projectDescription = 'A bundle of Chronic, Prettytime, and org.joda.time.format optimized for Java 8 Time API'
|
||||||
|
scmUrl = 'https://github.com/xbib/time'
|
||||||
|
scmConnection = 'scm:git:git://github.com/xbib/time.git'
|
||||||
|
scmDeveloperConnection = 'scm:git:git://github.com/xbib/time.git'
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
apply plugin: 'idea'
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
outputDir file('build/classes/java/main')
|
|
||||||
testOutputDir file('build/classes/java/test')
|
|
||||||
}
|
|
||||||
}
|
|
63
gradle/publish.gradle
Normal file
63
gradle/publish.gradle
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
task xbibUpload(type: Upload) {
|
||||||
|
configuration = configurations.archives
|
||||||
|
uploadDescriptor = true
|
||||||
|
repositories {
|
||||||
|
if (project.hasProperty('xbibUsername')) {
|
||||||
|
mavenDeployer {
|
||||||
|
configuration = configurations.wagon
|
||||||
|
repository(url: uri('scpexe://xbib.org/repository')) {
|
||||||
|
authentication(userName: xbibUsername, privateKey: xbibPrivateKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task sonatypeUpload(type: Upload) {
|
||||||
|
configuration = configurations.archives
|
||||||
|
uploadDescriptor = true
|
||||||
|
repositories {
|
||||||
|
if (project.hasProperty('ossrhUsername')) {
|
||||||
|
mavenDeployer {
|
||||||
|
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||||
|
repository(url: uri(ossrhReleaseUrl)) {
|
||||||
|
authentication(userName: ossrhUsername, password: ossrhPassword)
|
||||||
|
}
|
||||||
|
snapshotRepository(url: uri(ossrhSnapshotUrl)) {
|
||||||
|
authentication(userName: ossrhUsername, password: ossrhPassword)
|
||||||
|
}
|
||||||
|
pom.project {
|
||||||
|
name projectName
|
||||||
|
description projectDescription
|
||||||
|
packaging 'jar'
|
||||||
|
inceptionYear '2016'
|
||||||
|
url scmUrl
|
||||||
|
organization {
|
||||||
|
name 'xbib'
|
||||||
|
url 'http://xbib.org'
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id user
|
||||||
|
name 'Jörg Prante'
|
||||||
|
email 'joergprante@gmail.com'
|
||||||
|
url 'https://github.com/jprante'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
url scmUrl
|
||||||
|
connection scmConnection
|
||||||
|
developerConnection scmDeveloperConnection
|
||||||
|
}
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name 'The Apache License, Version 2.0'
|
||||||
|
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
if (project.hasProperty('forgeJoToken')) {
|
|
||||||
publishing {
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url 'https://xbib.org/api/packages/joerg/maven'
|
|
||||||
credentials(HttpHeaderCredentials) {
|
|
||||||
name = "Authorization"
|
|
||||||
value = "token ${project.property('forgeJoToken')}"
|
|
||||||
}
|
|
||||||
authentication {
|
|
||||||
header(HttpHeaderAuthentication)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
apply plugin: 'ivy-publish'
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
repositories {
|
|
||||||
ivy {
|
|
||||||
url = "https://xbib.org/repo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
publications {
|
|
||||||
ivy(IvyPublication) {
|
|
||||||
from components.java
|
|
||||||
descriptor {
|
|
||||||
license {
|
|
||||||
name = 'The Apache License, Version 2.0'
|
|
||||||
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
|
||||||
}
|
|
||||||
author {
|
|
||||||
name = 'Jörg Prante'
|
|
||||||
url = 'https://xbib.org/joerg'
|
|
||||||
}
|
|
||||||
descriptor.description {
|
|
||||||
text = rootProject.ext.description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
"${project.name}"(MavenPublication) {
|
|
||||||
from components.java
|
|
||||||
pom {
|
|
||||||
artifactId = project.name
|
|
||||||
name = project.name
|
|
||||||
description = rootProject.ext.description
|
|
||||||
url = rootProject.ext.url
|
|
||||||
inceptionYear = rootProject.ext.inceptionYear
|
|
||||||
packaging = 'jar'
|
|
||||||
organization {
|
|
||||||
name = 'xbib'
|
|
||||||
url = 'https://xbib.org'
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id = 'joerg'
|
|
||||||
name = 'Jörg Prante'
|
|
||||||
email = 'joergprante@gmail.com'
|
|
||||||
url = 'https://xbib.org/joerg'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scm {
|
|
||||||
url = rootProject.ext.scmUrl
|
|
||||||
connection = rootProject.ext.scmConnection
|
|
||||||
developerConnection = rootProject.ext.scmDeveloperConnection
|
|
||||||
}
|
|
||||||
issueManagement {
|
|
||||||
system = rootProject.ext.issueManagementSystem
|
|
||||||
url = rootProject.ext.issueManagementUrl
|
|
||||||
}
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name = rootProject.ext.licenseName
|
|
||||||
url = rootProject.ext.licenseUrl
|
|
||||||
distribution = 'repo'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (project.hasProperty("signing.keyId")) {
|
|
||||||
apply plugin: 'signing'
|
|
||||||
signing {
|
|
||||||
sign publishing.publications."${project.name}"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) {
|
|
||||||
nexusPublishing {
|
|
||||||
repositories {
|
|
||||||
sonatype {
|
|
||||||
username = project.property('ossrhUsername')
|
|
||||||
password = project.property('ossrhPassword')
|
|
||||||
packageGroup = "org.xbib"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
|
|
||||||
apply plugin: 'checkstyle'
|
|
||||||
|
|
||||||
tasks.withType(Checkstyle) {
|
|
||||||
ignoreFailures = true
|
|
||||||
reports {
|
|
||||||
xml.getRequired().set(true)
|
|
||||||
html.getRequired().set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkstyle {
|
|
||||||
configFile = rootProject.file('gradle/quality/checkstyle.xml')
|
|
||||||
ignoreFailures = true
|
|
||||||
showViolations = true
|
|
||||||
checkstyleMain {
|
|
||||||
source = sourceSets.main.allSource
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
cyclonedxBom {
|
|
||||||
includeConfigs = [ 'runtimeClasspath' ]
|
|
||||||
skipConfigs = [ 'compileClasspath', 'testCompileClasspath' ]
|
|
||||||
projectType = "library"
|
|
||||||
schemaVersion = "1.4"
|
|
||||||
destination = file("build/reports")
|
|
||||||
outputName = "bom"
|
|
||||||
outputFormat = "json"
|
|
||||||
includeBomSerialNumber = true
|
|
||||||
componentVersion = "2.0.0"
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
apply plugin: 'pmd'
|
|
||||||
|
|
||||||
tasks.withType(Pmd) {
|
|
||||||
ignoreFailures = true
|
|
||||||
reports {
|
|
||||||
xml.getRequired().set(true)
|
|
||||||
html.getRequired().set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pmd {
|
|
||||||
ignoreFailures = true
|
|
||||||
consoleOutput = false
|
|
||||||
toolVersion = "6.51.0"
|
|
||||||
ruleSetFiles = rootProject.files('gradle/quality/pmd/category/java/bestpractices.xml')
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
rulesets.filenames=\
|
|
||||||
category/java/bestpractices.xml,\
|
|
||||||
category/java/codestyle.xml,\
|
|
||||||
category/java/design.xml,\
|
|
||||||
category/java/documentation.xml,\
|
|
||||||
category/java/errorprone.xml,\
|
|
||||||
category/java/multithreading.xml,\
|
|
||||||
category/java/performance.xml,\
|
|
||||||
category/java/security.xml
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,144 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<ruleset name="Documentation"
|
|
||||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
|
||||||
|
|
||||||
<description>
|
|
||||||
Rules that are related to code documentation.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<rule name="CommentContent"
|
|
||||||
since="5.0"
|
|
||||||
message="Invalid words or phrases found"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.documentation.CommentContentRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_documentation.html#commentcontent">
|
|
||||||
<description>
|
|
||||||
A rule for the politically correct... we don't want to offend anyone.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
//OMG, this is horrible, Bob is an idiot !!!
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="CommentRequired"
|
|
||||||
since="5.1"
|
|
||||||
message="Comment is required"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.documentation.CommentRequiredRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_documentation.html#commentrequired">
|
|
||||||
<description>
|
|
||||||
Denotes whether comments are required (or unwanted) for specific language elements.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Jon Doe
|
|
||||||
*/
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="CommentSize"
|
|
||||||
since="5.0"
|
|
||||||
message="Comment is too large"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.documentation.CommentSizeRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_documentation.html#commentsize">
|
|
||||||
<description>
|
|
||||||
Determines whether the dimensions of non-header comments found are within the specified limits.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* too many lines!
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UncommentedEmptyConstructor"
|
|
||||||
language="java"
|
|
||||||
since="3.4"
|
|
||||||
message="Document empty constructor"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
typeResolution="true"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_documentation.html#uncommentedemptyconstructor">
|
|
||||||
<description>
|
|
||||||
Uncommented Empty Constructor finds instances where a constructor does not
|
|
||||||
contain statements, but there is no comment. By explicitly commenting empty
|
|
||||||
constructors it is easier to distinguish between intentional (commented)
|
|
||||||
and unintentional empty constructors.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//ConstructorDeclaration[@Private='false']
|
|
||||||
[count(BlockStatement) = 0 and ($ignoreExplicitConstructorInvocation = 'true' or not(ExplicitConstructorInvocation)) and @containsComment = 'false']
|
|
||||||
[not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('javax.inject.Inject')])]
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
<property name="ignoreExplicitConstructorInvocation" type="Boolean" description="Ignore explicit constructor invocation when deciding whether constructor is empty or not" value="false"/>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public Foo() {
|
|
||||||
// This constructor is intentionally empty. Nothing special is needed here.
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UncommentedEmptyMethodBody"
|
|
||||||
language="java"
|
|
||||||
since="3.4"
|
|
||||||
message="Document empty method body"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_documentation.html#uncommentedemptymethodbody">
|
|
||||||
<description>
|
|
||||||
Uncommented Empty Method Body finds instances where a method body does not contain
|
|
||||||
statements, but there is no comment. By explicitly commenting empty method bodies
|
|
||||||
it is easier to distinguish between intentional (commented) and unintentional
|
|
||||||
empty methods.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//MethodDeclaration/Block[count(BlockStatement) = 0 and @containsComment = 'false']
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public void doSomething() {
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
</ruleset>
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,393 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<ruleset name="Multithreading"
|
|
||||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
|
||||||
|
|
||||||
<description>
|
|
||||||
Rules that flag issues when dealing with multiple threads of execution.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<rule name="AvoidSynchronizedAtMethodLevel"
|
|
||||||
language="java"
|
|
||||||
since="3.0"
|
|
||||||
message="Use block level rather than method level synchronization"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#avoidsynchronizedatmethodlevel">
|
|
||||||
<description>
|
|
||||||
Method-level synchronization can cause problems when new code is added to the method.
|
|
||||||
Block-level synchronization helps to ensure that only the code that needs synchronization
|
|
||||||
gets it.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>//MethodDeclaration[@Synchronized='true']</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
// Try to avoid this:
|
|
||||||
synchronized void foo() {
|
|
||||||
}
|
|
||||||
// Prefer this:
|
|
||||||
void bar() {
|
|
||||||
synchronized(this) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to avoid this for static methods:
|
|
||||||
static synchronized void fooStatic() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer this:
|
|
||||||
static void barStatic() {
|
|
||||||
synchronized(Foo.class) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="AvoidThreadGroup"
|
|
||||||
language="java"
|
|
||||||
since="3.6"
|
|
||||||
message="Avoid using java.lang.ThreadGroup; it is not thread safe"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
typeResolution="true"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#avoidthreadgroup">
|
|
||||||
<description>
|
|
||||||
Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment
|
|
||||||
it contains methods that are not thread-safe.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.ThreadGroup')]|
|
|
||||||
//PrimarySuffix[contains(@Image, 'getThreadGroup')]
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Bar {
|
|
||||||
void buz() {
|
|
||||||
ThreadGroup tg = new ThreadGroup("My threadgroup");
|
|
||||||
tg = new ThreadGroup(tg, "my thread group");
|
|
||||||
tg = Thread.currentThread().getThreadGroup();
|
|
||||||
tg = System.getSecurityManager().getThreadGroup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="AvoidUsingVolatile"
|
|
||||||
language="java"
|
|
||||||
since="4.1"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
message="Use of modifier volatile is not recommended."
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#avoidusingvolatile">
|
|
||||||
<description>
|
|
||||||
Use of the keyword 'volatile' is generally used to fine tune a Java application, and therefore, requires
|
|
||||||
a good expertise of the Java Memory Model. Moreover, its range of action is somewhat misknown. Therefore,
|
|
||||||
the volatile keyword should not be used for maintenance purpose and portability.
|
|
||||||
</description>
|
|
||||||
<priority>2</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>//FieldDeclaration[contains(@Volatile,'true')]</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class ThrDeux {
|
|
||||||
private volatile String var1; // not suggested
|
|
||||||
private String var2; // preferred
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="DoNotUseThreads"
|
|
||||||
language="java"
|
|
||||||
since="4.1"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
message="To be compliant to J2EE, a webapp should not use any thread."
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#donotusethreads">
|
|
||||||
<description>
|
|
||||||
The J2EE specification explicitly forbids the use of threads.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>//ClassOrInterfaceType[@Image = 'Thread' or @Image = 'Runnable']</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
// This is not allowed
|
|
||||||
public class UsingThread extends Thread {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neither this,
|
|
||||||
public class OtherThread implements Runnable {
|
|
||||||
// Nor this ...
|
|
||||||
public void methode() {
|
|
||||||
Runnable thread = new Thread(); thread.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="DontCallThreadRun"
|
|
||||||
language="java"
|
|
||||||
since="4.3"
|
|
||||||
message="Don't call Thread.run() explicitly, use Thread.start()"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
typeResolution="true"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#dontcallthreadrun">
|
|
||||||
<description>
|
|
||||||
Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, call Thread.start() for the intended behavior.
|
|
||||||
</description>
|
|
||||||
<priority>4</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//StatementExpression/PrimaryExpression
|
|
||||||
[
|
|
||||||
PrimaryPrefix
|
|
||||||
[
|
|
||||||
./Name[ends-with(@Image, '.run') or @Image = 'run']
|
|
||||||
and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image
|
|
||||||
[../../../Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]]
|
|
||||||
or (./AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]
|
|
||||||
and ../PrimarySuffix[@Image = 'run'])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
Thread t = new Thread();
|
|
||||||
t.run(); // use t.start() instead
|
|
||||||
new Thread().run(); // same violation
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="DoubleCheckedLocking"
|
|
||||||
language="java"
|
|
||||||
since="1.04"
|
|
||||||
message="Double checked locking is not thread safe in Java."
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.multithreading.DoubleCheckedLockingRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#doublecheckedlocking">
|
|
||||||
<description>
|
|
||||||
Partially created objects can be returned by the Double Checked Locking pattern when used in Java.
|
|
||||||
An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the
|
|
||||||
reference points to.
|
|
||||||
|
|
||||||
Note: With Java 5, you can make Double checked locking work, if you declare the variable to be `volatile`.
|
|
||||||
|
|
||||||
For more details refer to: <http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html>
|
|
||||||
or <http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html>
|
|
||||||
</description>
|
|
||||||
<priority>1</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
/*volatile */ Object baz = null; // fix for Java5 and later: volatile
|
|
||||||
Object bar() {
|
|
||||||
if (baz == null) { // baz may be non-null yet not fully created
|
|
||||||
synchronized(this) {
|
|
||||||
if (baz == null) {
|
|
||||||
baz = new Object();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return baz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="NonThreadSafeSingleton"
|
|
||||||
since="3.4"
|
|
||||||
message="Singleton is not thread safe"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.multithreading.NonThreadSafeSingletonRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#nonthreadsafesingleton">
|
|
||||||
<description>
|
|
||||||
Non-thread safe singletons can result in bad state changes. Eliminate
|
|
||||||
static singletons if possible by instantiating the object directly. Static
|
|
||||||
singletons are usually not needed as only a single instance exists anyway.
|
|
||||||
Other possible fixes are to synchronize the entire method or to use an
|
|
||||||
[initialize-on-demand holder class](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom).
|
|
||||||
|
|
||||||
Refrain from using the double-checked locking pattern. The Java Memory Model doesn't
|
|
||||||
guarantee it to work unless the variable is declared as `volatile`, adding an uneeded
|
|
||||||
performance penalty. [Reference](http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)
|
|
||||||
|
|
||||||
See Effective Java, item 48.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
private static Foo foo = null;
|
|
||||||
|
|
||||||
//multiple simultaneous callers may see partially initialized objects
|
|
||||||
public static Foo getFoo() {
|
|
||||||
if (foo==null) {
|
|
||||||
foo = new Foo();
|
|
||||||
}
|
|
||||||
return foo;
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UnsynchronizedStaticDateFormatter"
|
|
||||||
since="3.6"
|
|
||||||
deprecated="true"
|
|
||||||
message="Static DateFormatter objects should be accessed in a synchronized manner"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.multithreading.UnsynchronizedStaticDateFormatterRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#unsynchronizedstaticdateformatter">
|
|
||||||
<description>
|
|
||||||
SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances
|
|
||||||
for each thread. If multiple threads must access a static formatter, the formatter must be
|
|
||||||
synchronized either on method or block level.
|
|
||||||
|
|
||||||
This rule has been deprecated in favor of the rule {% rule UnsynchronizedStaticFormatter %}.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
private static final SimpleDateFormat sdf = new SimpleDateFormat();
|
|
||||||
void bar() {
|
|
||||||
sdf.format(); // poor, no thread-safety
|
|
||||||
}
|
|
||||||
synchronized void foo() {
|
|
||||||
sdf.format(); // preferred
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UnsynchronizedStaticFormatter"
|
|
||||||
since="6.11.0"
|
|
||||||
message="Static Formatter objects should be accessed in a synchronized manner"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.multithreading.UnsynchronizedStaticFormatterRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#unsynchronizedstaticformatter">
|
|
||||||
<description>
|
|
||||||
Instances of `java.text.Format` are generally not synchronized.
|
|
||||||
Sun recommends using separate format instances for each thread.
|
|
||||||
If multiple threads must access a static formatter, the formatter must be
|
|
||||||
synchronized either on method or block level.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
private static final SimpleDateFormat sdf = new SimpleDateFormat();
|
|
||||||
void bar() {
|
|
||||||
sdf.format(); // poor, no thread-safety
|
|
||||||
}
|
|
||||||
synchronized void foo() {
|
|
||||||
sdf.format(); // preferred
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UseConcurrentHashMap"
|
|
||||||
language="java"
|
|
||||||
minimumLanguageVersion="1.5"
|
|
||||||
since="4.2.6"
|
|
||||||
message="If you run in Java5 or newer and have concurrent access, you should use the ConcurrentHashMap implementation"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#useconcurrenthashmap">
|
|
||||||
<description>
|
|
||||||
Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can
|
|
||||||
perform efficient map reads without blocking other threads.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//Type[../VariableDeclarator/VariableInitializer//AllocationExpression/ClassOrInterfaceType[@Image != 'ConcurrentHashMap']]
|
|
||||||
/ReferenceType/ClassOrInterfaceType[@Image = 'Map']
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class ConcurrentApp {
|
|
||||||
public void getMyInstance() {
|
|
||||||
Map map1 = new HashMap(); // fine for single-threaded access
|
|
||||||
Map map2 = new ConcurrentHashMap(); // preferred for use with multiple threads
|
|
||||||
|
|
||||||
// the following case will be ignored by this rule
|
|
||||||
Map map3 = someModule.methodThatReturnMap(); // might be OK, if the returned map is already thread-safe
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UseNotifyAllInsteadOfNotify"
|
|
||||||
language="java"
|
|
||||||
since="3.0"
|
|
||||||
message="Call Thread.notifyAll() rather than Thread.notify()"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#usenotifyallinsteadofnotify">
|
|
||||||
<description>
|
|
||||||
Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only
|
|
||||||
one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//StatementExpression/PrimaryExpression
|
|
||||||
[PrimarySuffix/Arguments[@ArgumentCount = '0']]
|
|
||||||
[
|
|
||||||
PrimaryPrefix[
|
|
||||||
./Name[@Image='notify' or ends-with(@Image,'.notify')]
|
|
||||||
or ../PrimarySuffix/@Image='notify'
|
|
||||||
or (./AllocationExpression and ../PrimarySuffix[@Image='notify'])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
void bar() {
|
|
||||||
x.notify();
|
|
||||||
// If many threads are monitoring x, only one (and you won't know which) will be notified.
|
|
||||||
// use instead:
|
|
||||||
x.notifyAll();
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
</ruleset>
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,65 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<ruleset name="Security" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
|
||||||
|
|
||||||
<description>
|
|
||||||
Rules that flag potential security flaws.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<rule name="HardCodedCryptoKey"
|
|
||||||
since="6.4.0"
|
|
||||||
message="Do not use hard coded encryption keys"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.security.HardCodedCryptoKeyRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_security.html#hardcodedcryptokey">
|
|
||||||
<description>
|
|
||||||
Do not use hard coded values for cryptographic operations. Please store keys outside of source code.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
void good() {
|
|
||||||
SecretKeySpec secretKeySpec = new SecretKeySpec(Properties.getKey(), "AES");
|
|
||||||
}
|
|
||||||
|
|
||||||
void bad() {
|
|
||||||
SecretKeySpec secretKeySpec = new SecretKeySpec("my secret here".getBytes(), "AES");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="InsecureCryptoIv"
|
|
||||||
since="6.3.0"
|
|
||||||
message="Do not use hard coded initialization vector in crypto operations"
|
|
||||||
class="net.sourceforge.pmd.lang.java.rule.security.InsecureCryptoIvRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_security.html#insecurecryptoiv">
|
|
||||||
<description>
|
|
||||||
Do not use hard coded initialization vector in cryptographic operations. Please use a randomly generated IV.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
void good() {
|
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte iv[] = new byte[16];
|
|
||||||
random.nextBytes(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bad() {
|
|
||||||
byte[] iv = new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, };
|
|
||||||
}
|
|
||||||
|
|
||||||
void alsoBad() {
|
|
||||||
byte[] iv = "secret iv in here".getBytes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
</ruleset>
|
|
|
@ -1,37 +0,0 @@
|
||||||
|
|
||||||
subprojects {
|
|
||||||
|
|
||||||
sonarqube {
|
|
||||||
properties {
|
|
||||||
property "sonar.projectName", "${project.group} ${project.name}"
|
|
||||||
property "sonar.sourceEncoding", "UTF-8"
|
|
||||||
property "sonar.tests", "src/test/java"
|
|
||||||
property "sonar.scm.provider", "git"
|
|
||||||
property "sonar.junit.reportsPath", "build/test-results/test/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tasks.withType(Pmd) {
|
|
||||||
ignoreFailures = true
|
|
||||||
reports {
|
|
||||||
xml.enabled = true
|
|
||||||
html.enabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
spotbugs {
|
|
||||||
effort = "max"
|
|
||||||
reportLevel = "low"
|
|
||||||
//includeFilter = file("findbugs-exclude.xml")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(com.github.spotbugs.SpotBugsTask) {
|
|
||||||
ignoreFailures = true
|
|
||||||
reports {
|
|
||||||
xml.enabled = false
|
|
||||||
html.enabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
apply plugin: 'com.github.spotbugs'
|
|
||||||
|
|
||||||
spotbugs {
|
|
||||||
effort = "max"
|
|
||||||
reportLevel = "low"
|
|
||||||
ignoreFailures = true
|
|
||||||
}
|
|
||||||
|
|
||||||
spotbugsMain {
|
|
||||||
reports {
|
|
||||||
xml.getRequired().set(false)
|
|
||||||
html.getRequired().set(true)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
repositories {
|
|
||||||
mavenLocal()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
36
gradle/sonarqube.gradle
Normal file
36
gradle/sonarqube.gradle
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
tasks.withType(FindBugs) {
|
||||||
|
ignoreFailures = true
|
||||||
|
reports {
|
||||||
|
xml.enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks.withType(Pmd) {
|
||||||
|
ignoreFailures = true
|
||||||
|
reports {
|
||||||
|
xml.enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks.withType(Checkstyle) {
|
||||||
|
ignoreFailures = true
|
||||||
|
reports {
|
||||||
|
xml.enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jacocoTestReport {
|
||||||
|
reports {
|
||||||
|
xml.enabled true
|
||||||
|
xml.destination "${buildDir}/reports/jacoco-xml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sonarqube {
|
||||||
|
properties {
|
||||||
|
property "sonar.projectName", "${project.group} ${project.name}"
|
||||||
|
property "sonar.sourceEncoding", "UTF-8"
|
||||||
|
property "sonar.tests", "src/test/java"
|
||||||
|
property "sonar.scm.provider", "git"
|
||||||
|
property "sonar.java.coveragePlugin", "jacoco"
|
||||||
|
property "sonar.junit.reportsPath", "build/test-results/test/"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
dependencies {
|
|
||||||
testImplementation testLibs.junit.jupiter.api
|
|
||||||
testImplementation testLibs.junit.jupiter.params
|
|
||||||
testImplementation testLibs.hamcrest
|
|
||||||
testRuntimeOnly testLibs.junit.jupiter.engine
|
|
||||||
testRuntimeOnly testLibs.junit.jupiter.platform.launcher
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
failFast = true
|
|
||||||
testLogging {
|
|
||||||
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
|
||||||
}
|
|
||||||
afterSuite { desc, result ->
|
|
||||||
if (!desc.parent) {
|
|
||||||
println "\nTest result: ${result.resultType}"
|
|
||||||
println "Test summary: ${result.testCount} tests, " +
|
|
||||||
"${result.successfulTestCount} succeeded, " +
|
|
||||||
"${result.failedTestCount} failed, " +
|
|
||||||
"${result.skippedTestCount} skipped"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// for Guava using reflection on JDK classes which JDK17 does not like
|
|
||||||
jvmArgs '--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED',
|
|
||||||
'--add-exports=java.base/jdk.internal.ref=ALL-UNNAMED',
|
|
||||||
'--add-exports=java.base/sun.nio.ch=ALL-UNNAMED',
|
|
||||||
'--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED',
|
|
||||||
'--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',
|
|
||||||
'--add-opens=jdk.compiler/com.sun.tools.javac=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.base/java.lang=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.base/java.lang.reflect=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.base/java.io=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.base/java.util=ALL-UNNAMED'
|
|
||||||
|
|
||||||
}
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,7 +1,6 @@
|
||||||
|
#Wed Nov 30 14:21:32 CET 2016
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
|
|
||||||
networkTimeout=10000
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-all.zip
|
||||||
|
|
303
gradlew
vendored
303
gradlew
vendored
|
@ -1,127 +1,78 @@
|
||||||
#!/bin/sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright © 2015-2021 the original authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
##
|
||||||
# Gradle start up script for POSIX generated by Gradle.
|
## Gradle start up script for UN*X
|
||||||
#
|
##
|
||||||
# Important for running:
|
|
||||||
#
|
|
||||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
|
||||||
# noncompliant, but you have some other compliant shell such as ksh or
|
|
||||||
# bash, then to run this script, type that shell name before the whole
|
|
||||||
# command line, like:
|
|
||||||
#
|
|
||||||
# ksh Gradle
|
|
||||||
#
|
|
||||||
# Busybox and similar reduced shells will NOT work, because this script
|
|
||||||
# requires all of these POSIX shell features:
|
|
||||||
# * functions;
|
|
||||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
|
||||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
|
||||||
# * compound commands having a testable exit status, especially «case»;
|
|
||||||
# * various built-in commands including «command», «set», and «ulimit».
|
|
||||||
#
|
|
||||||
# Important for patching:
|
|
||||||
#
|
|
||||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
|
||||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
|
||||||
#
|
|
||||||
# The "traditional" practice of packing multiple parameters into a
|
|
||||||
# space-separated string is a well documented source of bugs and security
|
|
||||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
|
||||||
# options in "$@", and eventually passing that to Java.
|
|
||||||
#
|
|
||||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
|
||||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
|
||||||
# see the in-line comments for details.
|
|
||||||
#
|
|
||||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
|
||||||
# Darwin, MinGW, and NonStop.
|
|
||||||
#
|
|
||||||
# (3) This script is generated from the Groovy template
|
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
|
||||||
# within the Gradle project.
|
|
||||||
#
|
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
|
||||||
#
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
app_path=$0
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
# Need this for daisy-chained symlinks.
|
while [ -h "$PRG" ] ; do
|
||||||
while
|
ls=`ls -ld "$PRG"`
|
||||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
[ -h "$app_path" ]
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
do
|
PRG="$link"
|
||||||
ls=$( ls -ld "$app_path" )
|
else
|
||||||
link=${ls#*' -> '}
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
case $link in #(
|
fi
|
||||||
/*) app_path=$link ;; #(
|
|
||||||
*) app_path=$APP_HOME$link ;;
|
|
||||||
esac
|
|
||||||
done
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
# This is normally unused
|
APP_NAME="Gradle"
|
||||||
# shellcheck disable=SC2034
|
APP_BASE_NAME=`basename "$0"`
|
||||||
APP_BASE_NAME=${0##*/}
|
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD="maximum"
|
||||||
|
|
||||||
warn ( ) {
|
warn ( ) {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
} >&2
|
}
|
||||||
|
|
||||||
die ( ) {
|
die ( ) {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
} >&2
|
}
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "$( uname )" in #(
|
case "`uname`" in
|
||||||
CYGWIN* ) cygwin=true ;; #(
|
CYGWIN* )
|
||||||
Darwin* ) darwin=true ;; #(
|
cygwin=true
|
||||||
MSYS* | MINGW* ) msys=true ;; #(
|
;;
|
||||||
NONSTOP* ) nonstop=true ;;
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
else
|
else
|
||||||
JAVACMD=$JAVA_HOME/bin/java
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
@ -130,120 +81,92 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD="java"
|
||||||
if ! command -v java >/dev/null 2>&1
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
case $MAX_FD in #(
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
max*)
|
if [ $? -eq 0 ] ; then
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
# shellcheck disable=SC2039,SC3045
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
fi
|
||||||
warn "Could not query maximum file descriptor limit"
|
ulimit -n $MAX_FD
|
||||||
esac
|
if [ $? -ne 0 ] ; then
|
||||||
case $MAX_FD in #(
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
'' | soft) :;; #(
|
fi
|
||||||
*)
|
else
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
# shellcheck disable=SC2039,SC3045
|
fi
|
||||||
ulimit -n "$MAX_FD" ||
|
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
|
||||||
esac
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command, stacking in reverse order:
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
# * args from the command line
|
if $darwin; then
|
||||||
# * the main class name
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
# * -classpath
|
|
||||||
# * -D...appname settings
|
|
||||||
# * --module-path (only if needed)
|
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if "$cygwin" || "$msys" ; then
|
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
|
||||||
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
for arg do
|
|
||||||
if
|
|
||||||
case $arg in #(
|
|
||||||
-*) false ;; # don't mess with options #(
|
|
||||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
|
||||||
[ -e "$t" ] ;; #(
|
|
||||||
*) false ;;
|
|
||||||
esac
|
|
||||||
then
|
|
||||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
|
||||||
fi
|
fi
|
||||||
# Roll the args list around exactly as many times as the number of
|
|
||||||
# args, so each arg winds up back in the position where it started, but
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
# possibly modified.
|
if $cygwin ; then
|
||||||
#
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
# NB: a `for` loop captures its iteration list before it begins, so
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
# changing the positional parameters here affects neither the number of
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
# iterations, nor the values presented in `arg`.
|
|
||||||
shift # remove old arg
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
set -- "$@" "$arg" # push replacement arg
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
done
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save ( ) {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
# and any embedded shellness will be escaped.
|
cd "$(dirname "$0")"
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
||||||
# treated as '${Hostname}' itself on the command line.
|
|
||||||
|
|
||||||
set -- \
|
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
|
||||||
-classpath "$CLASSPATH" \
|
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
|
||||||
if ! command -v xargs >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
die "xargs is not available"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
|
||||||
#
|
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
|
||||||
#
|
|
||||||
# In Bash we could simply go:
|
|
||||||
#
|
|
||||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
|
||||||
# set -- "${ARGS[@]}" "$@"
|
|
||||||
#
|
|
||||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
|
||||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
|
||||||
# character that might be a shell metacharacter, then use eval to reverse
|
|
||||||
# that process (while maintaining the separation between arguments), and wrap
|
|
||||||
# the whole thing up as a single "set" statement.
|
|
||||||
#
|
|
||||||
# This will of course break if any of these variables contains a newline or
|
|
||||||
# an unmatched quote.
|
|
||||||
#
|
|
||||||
|
|
||||||
eval "set -- $(
|
|
||||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
|
||||||
xargs -n1 |
|
|
||||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
|
||||||
tr '\n' ' '
|
|
||||||
)" '"$@"'
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|
72
gradlew.bat
vendored
72
gradlew.bat
vendored
|
@ -1,19 +1,3 @@
|
||||||
@rem
|
|
||||||
@rem Copyright 2015 the original author or authors.
|
|
||||||
@rem
|
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
@rem you may not use this file except in compliance with the License.
|
|
||||||
@rem You may obtain a copy of the License at
|
|
||||||
@rem
|
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@rem
|
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
@rem See the License for the specific language governing permissions and
|
|
||||||
@rem limitations under the License.
|
|
||||||
@rem
|
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
|
@ -26,28 +10,24 @@ if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
@rem This is normally unused
|
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -55,36 +35,48 @@ goto fail
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
exit /b 1
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
|
||||||
exit /b %EXIT_CODE%
|
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
|
@ -1,33 +1 @@
|
||||||
pluginManagement {
|
rootProject.name = name
|
||||||
repositories {
|
|
||||||
mavenLocal()
|
|
||||||
mavenCentral {
|
|
||||||
metadataSources {
|
|
||||||
mavenPom()
|
|
||||||
artifact()
|
|
||||||
ignoreGradleMetadataRedirection()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
|
||||||
versionCatalogs {
|
|
||||||
libs {
|
|
||||||
version('gradle', '8.7')
|
|
||||||
}
|
|
||||||
testLibs {
|
|
||||||
version('junit', '5.10.2')
|
|
||||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
|
||||||
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
|
||||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
|
||||||
library('junit-jupiter-platform-launcher', 'org.junit.platform', 'junit-platform-launcher').version('1.10.0')
|
|
||||||
library('hamcrest', 'org.hamcrest', 'hamcrest-library').version('2.2')
|
|
||||||
library('junit4', 'junit', 'junit').version('4.13.2')
|
|
||||||
library('quartz', 'org.quartz-scheduler', 'quartz').version('2.3.2')
|
|
||||||
library('caliper', 'com.google.caliper', 'caliper').version('1.0-beta-3')
|
|
||||||
library('guava', 'com.google.guava', 'guava').version('32.1.3-jre')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
module org.xbib.time {
|
|
||||||
exports org.xbib.time.chronic;
|
|
||||||
exports org.xbib.time.chronic.handlers;
|
|
||||||
exports org.xbib.time.chronic.numerizer;
|
|
||||||
exports org.xbib.time.chronic.repeaters;
|
|
||||||
exports org.xbib.time.chronic.tags;
|
|
||||||
exports org.xbib.time.format;
|
|
||||||
exports org.xbib.time.pretty;
|
|
||||||
exports org.xbib.time.pretty.i18n;
|
|
||||||
exports org.xbib.time.pretty.units;
|
|
||||||
exports org.xbib.time.schedule;
|
|
||||||
}
|
|
|
@ -13,12 +13,16 @@ import org.xbib.time.chronic.tags.TimeZone;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Chronic {
|
public class Chronic {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(Chronic.class.getName());
|
||||||
|
|
||||||
private Chronic() {
|
private Chronic() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,39 +33,39 @@ public class Chronic {
|
||||||
/**
|
/**
|
||||||
* Parses a string containing a natural language date or time. If the parser
|
* Parses a string containing a natural language date or time. If the parser
|
||||||
* can find a date or time, either a Time or Chronic::Span will be returned
|
* can find a date or time, either a Time or Chronic::Span will be returned
|
||||||
* (depending on the value of {@code :guess}). If no date or time can be found,
|
* (depending on the value of <tt>:guess</tt>). If no date or time can be found,
|
||||||
* +nil+ will be returned.
|
* +nil+ will be returned.
|
||||||
* <p>
|
* <p>
|
||||||
* Options are:
|
* Options are:
|
||||||
* <p>
|
* <p>
|
||||||
* [{@code :context}]
|
* [<tt>:context</tt>]
|
||||||
* {@code :past} or {@code :future} (defaults to {@code :future})
|
* <tt>:past</tt> or <tt>:future</tt> (defaults to <tt>:future</tt>)
|
||||||
* <p>
|
* <p>
|
||||||
* If your string represents a birthday, you can set {@code :context} to {@code :past}
|
* If your string represents a birthday, you can set <tt>:context</tt> to <tt>:past</tt>
|
||||||
* and if an ambiguous string is given, it will assume it is in the
|
* and if an ambiguous string is given, it will assume it is in the
|
||||||
* past. Specify {@code :future<} or omit to set a future context.
|
* past. Specify <tt>:future</tt> or omit to set a future context.
|
||||||
* <p>
|
* <p>
|
||||||
* [{@code :now}]
|
* [<tt>:now</tt>]
|
||||||
* Time (defaults to Time.now)
|
* Time (defaults to Time.now)
|
||||||
* <p>
|
* <p>
|
||||||
* By setting {@code :now} to a Time, all computations will be based off
|
* By setting <tt>:now</tt> to a Time, all computations will be based off
|
||||||
* of that time instead of Time.now
|
* of that time instead of Time.now
|
||||||
* <p>
|
* <p>
|
||||||
* [{@code :guess<}]
|
* [<tt>:guess</tt>]
|
||||||
* +true+ or +false+ (defaults to +true+)
|
* +true+ or +false+ (defaults to +true+)
|
||||||
* <p>
|
* <p>
|
||||||
* By default, the parser will guess a single point in time for the
|
* By default, the parser will guess a single point in time for the
|
||||||
* given date or time. If you'd rather have the entire time span returned,
|
* given date or time. If you'd rather have the entire time span returned,
|
||||||
* set {@code :guess} to +false+ and a Chronic::Span will be returned.
|
* set <tt>:guess</tt> to +false+ and a Chronic::Span will be returned.
|
||||||
* <p>
|
* <p>
|
||||||
* [{@code :ambiguous_time_range}]
|
* [<tt>:ambiguous_time_range</tt>]
|
||||||
* Integer or {@code :none} (defaults to {@code 6} (6am-6pm))
|
* Integer or <tt>:none</tt> (defaults to <tt>6</tt> (6am-6pm))
|
||||||
* <p>
|
* <p>
|
||||||
* If an Integer is given, ambiguous times (like 5:00) will be
|
* If an Integer is given, ambiguous times (like 5:00) will be
|
||||||
* assumed to be within the range of that time in the AM to that time
|
* assumed to be within the range of that time in the AM to that time
|
||||||
* in the PM. For example, if you set it to {@code 7}, then the parser will
|
* in the PM. For example, if you set it to <tt>7</tt>, then the parser will
|
||||||
* look for the time between 7am and 7pm. In the case of 5:00, it would
|
* look for the time between 7am and 7pm. In the case of 5:00, it would
|
||||||
* assume that means 5:00pm. If {@code :none} is given, no assumption
|
* assume that means 5:00pm. If <tt>:none</tt> is given, no assumption
|
||||||
* will be made, and the first matching instance of that time will
|
* will be made, and the first matching instance of that time will
|
||||||
* be used.
|
* be used.
|
||||||
* @param text text
|
* @param text text
|
||||||
|
@ -80,6 +84,7 @@ public class Chronic {
|
||||||
tokens = (List<Token>) optionScannerClass.getMethod("scan", List.class, Options.class)
|
tokens = (List<Token>) optionScannerClass.getMethod("scan", List.class, Options.class)
|
||||||
.invoke(null, tokens, options);
|
.invoke(null, tokens, options);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
throw new ParseException("failed to scan tokens", 0);
|
throw new ParseException("failed to scan tokens", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +100,7 @@ public class Chronic {
|
||||||
tokens = (List<Token>) scannerClass.getMethod("scan", List.class, Options.class)
|
tokens = (List<Token>) scannerClass.getMethod("scan", List.class, Options.class)
|
||||||
.invoke(null, tokens, options);
|
.invoke(null, tokens, options);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
throw new ParseException("failed to scan tokens", 0);
|
throw new ParseException("failed to scan tokens", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.xbib.time.chronic;
|
package org.xbib.time.chronic;
|
||||||
|
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer;
|
||||||
|
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
@ -9,21 +9,15 @@ import java.time.ZonedDateTime;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Options {
|
public class Options {
|
||||||
|
|
||||||
private ZonedDateTime now;
|
private ZonedDateTime now;
|
||||||
|
|
||||||
private ZoneId zoneId;
|
private ZoneId zoneId;
|
||||||
|
private Pointer.PointerType context;
|
||||||
private PointerType context;
|
|
||||||
|
|
||||||
private boolean guess;
|
private boolean guess;
|
||||||
|
|
||||||
private int ambiguousTimeRange;
|
private int ambiguousTimeRange;
|
||||||
|
|
||||||
private boolean compatibilityMode;
|
private boolean compatibilityMode;
|
||||||
|
|
||||||
public Options() {
|
public Options() {
|
||||||
setContext(PointerType.FUTURE);
|
setContext(Pointer.PointerType.FUTURE);
|
||||||
setNow(ZonedDateTime.now());
|
setNow(ZonedDateTime.now());
|
||||||
setZoneId(ZoneId.of("GMT"));
|
setZoneId(ZoneId.of("GMT"));
|
||||||
setGuess(true);
|
setGuess(true);
|
||||||
|
@ -39,11 +33,11 @@ public class Options {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PointerType getContext() {
|
public Pointer.PointerType getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options setContext(PointerType context) {
|
public Options setContext(Pointer.PointerType context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,8 @@ package org.xbib.time.chronic;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Range {
|
public class Range {
|
||||||
|
private Long begin;
|
||||||
private final Long begin;
|
private Long end;
|
||||||
|
|
||||||
private final Long end;
|
|
||||||
|
|
||||||
public Range(long begin, long end) {
|
public Range(long begin, long end) {
|
||||||
this.begin = begin;
|
this.begin = begin;
|
||||||
|
|
|
@ -4,10 +4,8 @@ package org.xbib.time.chronic;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Tick {
|
public class Tick {
|
||||||
|
|
||||||
private int time;
|
private int time;
|
||||||
|
private boolean ambiguous;
|
||||||
private final boolean ambiguous;
|
|
||||||
|
|
||||||
public Tick(int time, boolean ambiguous) {
|
public Tick(int time, boolean ambiguous) {
|
||||||
this.time = time;
|
this.time = time;
|
||||||
|
|
|
@ -10,10 +10,8 @@ import java.util.List;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Token {
|
public class Token {
|
||||||
|
private String word;
|
||||||
private final String word;
|
private List<Tag<?>> tags;
|
||||||
|
|
||||||
private final List<Tag<?>> tags;
|
|
||||||
|
|
||||||
public Token(String word) {
|
public Token(String word) {
|
||||||
this.word = word;
|
this.word = word;
|
||||||
|
@ -37,7 +35,13 @@ public class Token {
|
||||||
* @param tagClass tag class
|
* @param tagClass tag class
|
||||||
*/
|
*/
|
||||||
public void untag(Class<?> tagClass) {
|
public void untag(Class<?> tagClass) {
|
||||||
tags.removeIf(tagClass::isInstance);
|
Iterator<Tag<?>> tagIter = tags.iterator();
|
||||||
|
while (tagIter.hasNext()) {
|
||||||
|
Tag<?> tag = tagIter.next();
|
||||||
|
if (tagClass.isInstance(tag)) {
|
||||||
|
tagIter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +58,7 @@ public class Token {
|
||||||
* @param <T> type parameter
|
* @param <T> type parameter
|
||||||
* @return tag
|
* @return tag
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Tag<?>> T getTag(Class<T> tagClass) {
|
public <T extends Tag<?>> T getTag(Class<T> tagClass) {
|
||||||
List<T> matches = getTags(tagClass);
|
List<T> matches = getTags(tagClass);
|
||||||
T matchingTag = null;
|
T matchingTag = null;
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.xbib.time.chronic.handlers;
|
||||||
import org.xbib.time.chronic.Options;
|
import org.xbib.time.chronic.Options;
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.repeaters.DayPortion;
|
|
||||||
import org.xbib.time.chronic.repeaters.EnumRepeaterDayPortion;
|
import org.xbib.time.chronic.repeaters.EnumRepeaterDayPortion;
|
||||||
import org.xbib.time.chronic.repeaters.IntegerRepeaterDayPortion;
|
import org.xbib.time.chronic.repeaters.IntegerRepeaterDayPortion;
|
||||||
import org.xbib.time.chronic.repeaters.Repeater;
|
import org.xbib.time.chronic.repeaters.Repeater;
|
||||||
|
@ -15,8 +14,7 @@ import org.xbib.time.chronic.tags.Grabber;
|
||||||
import org.xbib.time.chronic.tags.Ordinal;
|
import org.xbib.time.chronic.tags.Ordinal;
|
||||||
import org.xbib.time.chronic.tags.OrdinalDay;
|
import org.xbib.time.chronic.tags.OrdinalDay;
|
||||||
import org.xbib.time.chronic.tags.Pointer;
|
import org.xbib.time.chronic.tags.Pointer;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
import org.xbib.time.chronic.tags.Relative;
|
|
||||||
import org.xbib.time.chronic.tags.Scalar;
|
import org.xbib.time.chronic.tags.Scalar;
|
||||||
import org.xbib.time.chronic.tags.ScalarDay;
|
import org.xbib.time.chronic.tags.ScalarDay;
|
||||||
import org.xbib.time.chronic.tags.ScalarMonth;
|
import org.xbib.time.chronic.tags.ScalarMonth;
|
||||||
|
@ -204,7 +202,7 @@ public class Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Span getAnchor(List<Token> tokens, Options options) {
|
public static Span getAnchor(List<Token> tokens, Options options) {
|
||||||
Grabber grabber = new Grabber(Relative.THIS);
|
Grabber grabber = new Grabber(Grabber.Relative.THIS);
|
||||||
PointerType pointer = PointerType.FUTURE;
|
PointerType pointer = PointerType.FUTURE;
|
||||||
|
|
||||||
List<Repeater<?>> repeaters = getRepeaters(tokens);
|
List<Repeater<?>> repeaters = getRepeaters(tokens);
|
||||||
|
@ -221,16 +219,16 @@ public class Handler {
|
||||||
head.setNow(options.getNow());
|
head.setNow(options.getNow());
|
||||||
|
|
||||||
Span outerSpan;
|
Span outerSpan;
|
||||||
Relative grabberType = grabber.getType();
|
Grabber.Relative grabberType = grabber.getType();
|
||||||
if (grabberType == Relative.LAST) {
|
if (grabberType == Grabber.Relative.LAST) {
|
||||||
outerSpan = head.nextSpan(PointerType.PAST);
|
outerSpan = head.nextSpan(PointerType.PAST);
|
||||||
} else if (grabberType == Relative.THIS) {
|
} else if (grabberType == Grabber.Relative.THIS) {
|
||||||
if (!repeaters.isEmpty()) {
|
if (!repeaters.isEmpty()) {
|
||||||
outerSpan = head.thisSpan(PointerType.NONE);
|
outerSpan = head.thisSpan(PointerType.NONE);
|
||||||
} else {
|
} else {
|
||||||
outerSpan = head.thisSpan(options.getContext());
|
outerSpan = head.thisSpan(options.getContext());
|
||||||
}
|
}
|
||||||
} else if (grabberType == Relative.NEXT) {
|
} else if (grabberType == Grabber.Relative.NEXT) {
|
||||||
outerSpan = head.nextSpan(PointerType.FUTURE);
|
outerSpan = head.nextSpan(PointerType.FUTURE);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Invalid grabber type " + grabberType + ".");
|
throw new IllegalArgumentException("Invalid grabber type " + grabberType + ".");
|
||||||
|
@ -298,14 +296,14 @@ public class Handler {
|
||||||
Tag<RepeaterDayPortion<?>> t1Tag = t1.getTag(RepeaterDayPortion.class);
|
Tag<RepeaterDayPortion<?>> t1Tag = t1.getTag(RepeaterDayPortion.class);
|
||||||
|
|
||||||
Object t1TagType = t1Tag.getType();
|
Object t1TagType = t1Tag.getType();
|
||||||
if (DayPortion.MORNING.equals(t1TagType)) {
|
if (RepeaterDayPortion.DayPortion.MORNING.equals(t1TagType)) {
|
||||||
t1.untag(RepeaterDayPortion.class);
|
t1.untag(RepeaterDayPortion.class);
|
||||||
t1.tag(new EnumRepeaterDayPortion(DayPortion.AM));
|
t1.tag(new EnumRepeaterDayPortion(RepeaterDayPortion.DayPortion.AM));
|
||||||
} else if (DayPortion.AFTERNOON.equals(t1TagType) ||
|
} else if (RepeaterDayPortion.DayPortion.AFTERNOON.equals(t1TagType) ||
|
||||||
DayPortion.EVENING.equals(t1TagType) ||
|
RepeaterDayPortion.DayPortion.EVENING.equals(t1TagType) ||
|
||||||
DayPortion.NIGHT.equals(t1TagType)) {
|
RepeaterDayPortion.DayPortion.NIGHT.equals(t1TagType)) {
|
||||||
t1.untag(RepeaterDayPortion.class);
|
t1.untag(RepeaterDayPortion.class);
|
||||||
t1.tag(new EnumRepeaterDayPortion(DayPortion.PM));
|
t1.tag(new EnumRepeaterDayPortion(RepeaterDayPortion.DayPortion.PM));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@ package org.xbib.time.chronic.handlers;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class HandlerPattern {
|
public class HandlerPattern {
|
||||||
|
private boolean optional;
|
||||||
private final boolean optional;
|
|
||||||
|
|
||||||
public HandlerPattern(boolean optional) {
|
public HandlerPattern(boolean optional) {
|
||||||
this.optional = optional;
|
this.optional = optional;
|
||||||
|
|
|
@ -4,8 +4,7 @@ package org.xbib.time.chronic.handlers;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class HandlerTypePattern extends HandlerPattern {
|
public class HandlerTypePattern extends HandlerPattern {
|
||||||
|
private Handler.HandlerType type;
|
||||||
private final Handler.HandlerType type;
|
|
||||||
|
|
||||||
public HandlerTypePattern(Handler.HandlerType type) {
|
public HandlerTypePattern(Handler.HandlerType type) {
|
||||||
this(type, false);
|
this(type, false);
|
||||||
|
|
|
@ -11,6 +11,5 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface IHandler {
|
public interface IHandler {
|
||||||
|
|
||||||
Span handle(List<Token> tokens, Options options);
|
Span handle(List<Token> tokens, Options options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,5 @@ public class ORGRHandler extends ORRHandler {
|
||||||
Span outerSpan = Handler.getAnchor(tokens.subList(2, 4), options);
|
Span outerSpan = Handler.getAnchor(tokens.subList(2, 4), options);
|
||||||
return handle(tokens.subList(0, 2), outerSpan, options);
|
return handle(tokens.subList(0, 2), outerSpan, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.repeaters.Repeater;
|
import org.xbib.time.chronic.repeaters.Repeater;
|
||||||
import org.xbib.time.chronic.tags.Ordinal;
|
import org.xbib.time.chronic.tags.Ordinal;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer;
|
||||||
|
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,7 +21,7 @@ public abstract class ORRHandler implements IHandler {
|
||||||
Integer ordinalValue = tokens.get(0).getTag(Ordinal.class).getType();
|
Integer ordinalValue = tokens.get(0).getTag(Ordinal.class).getType();
|
||||||
Span span = null;
|
Span span = null;
|
||||||
for (int i = 0; i < ordinalValue; i++) {
|
for (int i = 0; i < ordinalValue; i++) {
|
||||||
span = repeater.nextSpan(PointerType.FUTURE);
|
span = repeater.nextSpan(Pointer.PointerType.FUTURE);
|
||||||
if (span.getBegin() > outerSpan.getEnd()) {
|
if (span.getBegin() > outerSpan.getEnd()) {
|
||||||
span = null;
|
span = null;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -16,4 +16,5 @@ public class ORSRHandler extends ORRHandler {
|
||||||
Span outerSpan = Handler.getAnchor(tokens.subList(3, 4), options);
|
Span outerSpan = Handler.getAnchor(tokens.subList(3, 4), options);
|
||||||
return handle(tokens.subList(0, 2), outerSpan, options);
|
return handle(tokens.subList(0, 2), outerSpan, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,5 @@ public class RHandler implements IHandler {
|
||||||
List<Token> ddTokens = Handler.dealiasAndDisambiguateTimes(tokens, options);
|
List<Token> ddTokens = Handler.dealiasAndDisambiguateTimes(tokens, options);
|
||||||
return Handler.getAnchor(ddTokens, options);
|
return Handler.getAnchor(ddTokens, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,16 @@ import org.xbib.time.chronic.tags.ScalarYear;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RdnRmnSdTTzSyHandler implements IHandler {
|
public class RdnRmnSdTTzSyHandler implements IHandler {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(RdnRmnSdTTzSyHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span handle(List<Token> tokens, Options options) {
|
public Span handle(List<Token> tokens, Options options) {
|
||||||
int month = tokens.get(1).getTag(RepeaterMonthName.class).getType().ordinal();
|
int month = tokens.get(1).getTag(RepeaterMonthName.class).getType().ordinal();
|
||||||
|
@ -26,6 +30,7 @@ public class RdnRmnSdTTzSyHandler implements IHandler {
|
||||||
ZonedDateTime dayStart = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, options.getZoneId());
|
ZonedDateTime dayStart = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, options.getZoneId());
|
||||||
span = Handler.dayOrTime(dayStart, timeTokens, options);
|
span = Handler.dayOrTime(dayStart, timeTokens, options);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
span = null;
|
span = null;
|
||||||
}
|
}
|
||||||
return span;
|
return span;
|
||||||
|
|
|
@ -9,12 +9,16 @@ import org.xbib.time.chronic.tags.ScalarYear;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RmnSdSyHandler implements IHandler {
|
public class RmnSdSyHandler implements IHandler {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(RmnSdSyHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span handle(List<Token> tokens, Options options) {
|
public Span handle(List<Token> tokens, Options options) {
|
||||||
int month = tokens.get(0).getTag(RepeaterMonthName.class).getType().ordinal();
|
int month = tokens.get(0).getTag(RepeaterMonthName.class).getType().ordinal();
|
||||||
|
@ -26,8 +30,10 @@ public class RmnSdSyHandler implements IHandler {
|
||||||
ZonedDateTime dayStart = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, options.getZoneId());
|
ZonedDateTime dayStart = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, options.getZoneId());
|
||||||
span = Handler.dayOrTime(dayStart, timeTokens, options);
|
span = Handler.dayOrTime(dayStart, timeTokens, options);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
span = null;
|
span = null;
|
||||||
}
|
}
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,16 @@ import org.xbib.time.chronic.tags.ScalarYear;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RmnSyHandler implements IHandler {
|
public class RmnSyHandler implements IHandler {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(RmnSyHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span handle(List<Token> tokens, Options options) {
|
public Span handle(List<Token> tokens, Options options) {
|
||||||
int month = tokens.get(0).getTag(RepeaterMonthName.class).getType().ordinal();
|
int month = tokens.get(0).getTag(RepeaterMonthName.class).getType().ordinal();
|
||||||
|
@ -25,8 +29,10 @@ public class RmnSyHandler implements IHandler {
|
||||||
ZonedDateTime end = start.plus(1, ChronoUnit.MONTHS);
|
ZonedDateTime end = start.plus(1, ChronoUnit.MONTHS);
|
||||||
span = new Span(start, end);
|
span = new Span(start, end);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
span = null;
|
span = null;
|
||||||
}
|
}
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,5 @@ public class SRPAHandler extends SRPHandler {
|
||||||
Span anchorSpan = Handler.getAnchor(tokens.subList(3, tokens.size()), options);
|
Span anchorSpan = Handler.getAnchor(tokens.subList(3, tokens.size()), options);
|
||||||
return super.handle(tokens, anchorSpan, options);
|
return super.handle(tokens, anchorSpan, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.repeaters.Repeater;
|
import org.xbib.time.chronic.repeaters.Repeater;
|
||||||
import org.xbib.time.chronic.tags.Pointer;
|
import org.xbib.time.chronic.tags.Pointer;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
|
||||||
import org.xbib.time.chronic.tags.Scalar;
|
import org.xbib.time.chronic.tags.Scalar;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
@ -20,7 +19,7 @@ public class SRPHandler implements IHandler {
|
||||||
public Span handle(List<Token> tokens, Span span, Options options) {
|
public Span handle(List<Token> tokens, Span span, Options options) {
|
||||||
int distance = tokens.get(0).getTag(Scalar.class).getType();
|
int distance = tokens.get(0).getTag(Scalar.class).getType();
|
||||||
Repeater<?> repeater = tokens.get(1).getTag(Repeater.class);
|
Repeater<?> repeater = tokens.get(1).getTag(Repeater.class);
|
||||||
PointerType pointer = tokens.get(2).getTag(Pointer.class).getType();
|
Pointer.PointerType pointer = tokens.get(2).getTag(Pointer.class).getType();
|
||||||
return repeater.getOffset(span, distance, pointer);
|
return repeater.getOffset(span, distance, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,5 @@ public class SdRmnSyHandler extends RmnSdSyHandler {
|
||||||
newTokens.addAll(tokens.subList(3, tokens.size()));
|
newTokens.addAll(tokens.subList(3, tokens.size()));
|
||||||
return super.handle(newTokens, options);
|
return super.handle(newTokens, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,4 +23,5 @@ public class SmSdHandler implements IHandler {
|
||||||
ZonedDateTime end = start.plus(1, ChronoUnit.MONTHS);
|
ZonedDateTime end = start.plus(1, ChronoUnit.MONTHS);
|
||||||
return new Span(start, end);
|
return new Span(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,16 @@ import org.xbib.time.chronic.tags.ScalarYear;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SmSdSyHandler implements IHandler {
|
public class SmSdSyHandler implements IHandler {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(SmSdSyHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span handle(List<Token> tokens, Options options) {
|
public Span handle(List<Token> tokens, Options options) {
|
||||||
int month = tokens.get(0).getTag(ScalarMonth.class).getType();
|
int month = tokens.get(0).getTag(ScalarMonth.class).getType();
|
||||||
|
@ -26,8 +30,10 @@ public class SmSdSyHandler implements IHandler {
|
||||||
ZonedDateTime dayStart = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, options.getZoneId());
|
ZonedDateTime dayStart = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, options.getZoneId());
|
||||||
span = Handler.dayOrTime(dayStart, timeTokens, options);
|
span = Handler.dayOrTime(dayStart, timeTokens, options);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
span = null;
|
span = null;
|
||||||
}
|
}
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,16 @@ import org.xbib.time.chronic.tags.ScalarYear;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SmSyHandler implements IHandler {
|
public class SmSyHandler implements IHandler {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(SmSyHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span handle(List<Token> tokens, Options options) {
|
public Span handle(List<Token> tokens, Options options) {
|
||||||
int month = tokens.get(0).getTag(ScalarMonth.class).getType();
|
int month = tokens.get(0).getTag(ScalarMonth.class).getType();
|
||||||
|
@ -25,8 +29,10 @@ public class SmSyHandler implements IHandler {
|
||||||
ZonedDateTime end = start.plus(1, ChronoUnit.MONTHS);
|
ZonedDateTime end = start.plus(1, ChronoUnit.MONTHS);
|
||||||
span = new Span(start, end);
|
span = new Span(start, end);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.log(Level.FINE, e.getMessage(), e);
|
||||||
span = null;
|
span = null;
|
||||||
}
|
}
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,7 @@ import org.xbib.time.chronic.tags.Tag;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public class TagPattern extends HandlerPattern {
|
public class TagPattern extends HandlerPattern {
|
||||||
|
private Class<? extends Tag> tagClass;
|
||||||
private final Class<? extends Tag> tagClass;
|
|
||||||
|
|
||||||
public TagPattern(Class<? extends Tag> tagClass) {
|
public TagPattern(Class<? extends Tag> tagClass) {
|
||||||
this(tagClass, false);
|
this(tagClass, false);
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class Numerizer {
|
||||||
directNums.add(new DirectNum("nine(\\W|$)", "9$1"));
|
directNums.add(new DirectNum("nine(\\W|$)", "9$1"));
|
||||||
directNums.add(new DirectNum("ten", "10"));
|
directNums.add(new DirectNum("ten", "10"));
|
||||||
directNums.add(new DirectNum("\\ba\\b", "1"));
|
directNums.add(new DirectNum("\\ba\\b", "1"));
|
||||||
DIRECT_NUMS = directNums.toArray(new DirectNum[0]);
|
DIRECT_NUMS = directNums.toArray(new DirectNum[directNums.size()]);
|
||||||
|
|
||||||
List<TenPrefix> tenPrefixes = new LinkedList<>();
|
List<TenPrefix> tenPrefixes = new LinkedList<>();
|
||||||
tenPrefixes.add(new TenPrefix("twenty", 20));
|
tenPrefixes.add(new TenPrefix("twenty", 20));
|
||||||
|
@ -60,7 +60,7 @@ public class Numerizer {
|
||||||
tenPrefixes.add(new TenPrefix("eighty", 80));
|
tenPrefixes.add(new TenPrefix("eighty", 80));
|
||||||
tenPrefixes.add(new TenPrefix("ninety", 90));
|
tenPrefixes.add(new TenPrefix("ninety", 90));
|
||||||
tenPrefixes.add(new TenPrefix("ninty", 90));
|
tenPrefixes.add(new TenPrefix("ninty", 90));
|
||||||
TEN_PREFIXES = tenPrefixes.toArray(new TenPrefix[0]);
|
TEN_PREFIXES = tenPrefixes.toArray(new TenPrefix[tenPrefixes.size()]);
|
||||||
|
|
||||||
List<BigPrefix> bigPrefixes = new LinkedList<>();
|
List<BigPrefix> bigPrefixes = new LinkedList<>();
|
||||||
bigPrefixes.add(new BigPrefix("hundred", 100L));
|
bigPrefixes.add(new BigPrefix("hundred", 100L));
|
||||||
|
@ -68,7 +68,7 @@ public class Numerizer {
|
||||||
bigPrefixes.add(new BigPrefix("million", 1000000L));
|
bigPrefixes.add(new BigPrefix("million", 1000000L));
|
||||||
bigPrefixes.add(new BigPrefix("billion", 1000000000L));
|
bigPrefixes.add(new BigPrefix("billion", 1000000000L));
|
||||||
bigPrefixes.add(new BigPrefix("trillion", 1000000000000L));
|
bigPrefixes.add(new BigPrefix("trillion", 1000000000000L));
|
||||||
BIG_PREFIXES = bigPrefixes.toArray(new BigPrefix[0]);
|
BIG_PREFIXES = bigPrefixes.toArray(new BigPrefix[bigPrefixes.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String numerize(String str) {
|
public static String numerize(String str) {
|
||||||
|
@ -81,7 +81,7 @@ public class Numerizer {
|
||||||
for (Prefix tp : Numerizer.TEN_PREFIXES) {
|
for (Prefix tp : Numerizer.TEN_PREFIXES) {
|
||||||
Matcher matcher = tp.getName().matcher(numerizedStr);
|
Matcher matcher = tp.getName().matcher(numerizedStr);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
StringBuilder matcherBuffer = new StringBuilder();
|
StringBuffer matcherBuffer = new StringBuffer();
|
||||||
do {
|
do {
|
||||||
if (matcher.group(1) == null) {
|
if (matcher.group(1) == null) {
|
||||||
matcher.appendReplacement(matcherBuffer, String.valueOf(tp.getNumber()));
|
matcher.appendReplacement(matcherBuffer, String.valueOf(tp.getNumber()));
|
||||||
|
@ -97,7 +97,7 @@ public class Numerizer {
|
||||||
for (Prefix bp : Numerizer.BIG_PREFIXES) {
|
for (Prefix bp : Numerizer.BIG_PREFIXES) {
|
||||||
Matcher matcher = bp.getName().matcher(numerizedStr);
|
Matcher matcher = bp.getName().matcher(numerizedStr);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
StringBuilder matcherBuffer = new StringBuilder();
|
StringBuffer matcherBuffer = new StringBuffer();
|
||||||
do {
|
do {
|
||||||
if (matcher.group(1) == null) {
|
if (matcher.group(1) == null) {
|
||||||
matcher.appendReplacement(matcherBuffer, String.valueOf(bp.getNumber()));
|
matcher.appendReplacement(matcherBuffer, String.valueOf(bp.getNumber()));
|
||||||
|
@ -113,7 +113,7 @@ public class Numerizer {
|
||||||
}
|
}
|
||||||
Matcher matcher = Numerizer.DEHAALFER.matcher(numerizedStr);
|
Matcher matcher = Numerizer.DEHAALFER.matcher(numerizedStr);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
StringBuilder matcherBuffer = new StringBuilder();
|
StringBuffer matcherBuffer = new StringBuffer();
|
||||||
do {
|
do {
|
||||||
matcher.appendReplacement(matcherBuffer,
|
matcher.appendReplacement(matcherBuffer,
|
||||||
String.valueOf(Float.parseFloat(matcher.group(1).trim()) + 0.5f));
|
String.valueOf(Float.parseFloat(matcher.group(1).trim()) + 0.5f));
|
||||||
|
@ -142,10 +142,8 @@ public class Numerizer {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static class DirectNum {
|
private static class DirectNum {
|
||||||
|
private Pattern name;
|
||||||
private final Pattern name;
|
private String number;
|
||||||
|
|
||||||
private final String number;
|
|
||||||
|
|
||||||
DirectNum(String name, String number) {
|
DirectNum(String name, String number) {
|
||||||
this.name = Pattern.compile(name, Pattern.CASE_INSENSITIVE);
|
this.name = Pattern.compile(name, Pattern.CASE_INSENSITIVE);
|
||||||
|
@ -165,10 +163,8 @@ public class Numerizer {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static class Prefix {
|
static class Prefix {
|
||||||
|
private Pattern name;
|
||||||
private final Pattern name;
|
private long number;
|
||||||
|
|
||||||
private final long number;
|
|
||||||
|
|
||||||
Prefix(Pattern name, long number) {
|
Prefix(Pattern name, long number) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum DayName {
|
|
||||||
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum DayPortion {
|
|
||||||
AM, PM, MORNING, AFTERNOON, EVENING, NIGHT
|
|
||||||
}
|
|
|
@ -5,18 +5,12 @@ import org.xbib.time.chronic.Range;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class EnumRepeaterDayPortion extends RepeaterDayPortion<DayPortion> {
|
public class EnumRepeaterDayPortion extends RepeaterDayPortion<RepeaterDayPortion.DayPortion> {
|
||||||
|
|
||||||
private static final Range AM_RANGE = new Range(0, 12 * 60 * 60); // 12am-12pm
|
private static final Range AM_RANGE = new Range(0, 12 * 60 * 60); // 12am-12pm
|
||||||
|
|
||||||
private static final Range PM_RANGE = new Range(12 * 60 * 60, 24 * 60 * 60 - 1); // 12pm-12am
|
private static final Range PM_RANGE = new Range(12 * 60 * 60, 24 * 60 * 60 - 1); // 12pm-12am
|
||||||
|
|
||||||
private static final Range MORNING_RANGE = new Range(6 * 60 * 60, 12 * 60 * 60); // 6am-12pm
|
private static final Range MORNING_RANGE = new Range(6 * 60 * 60, 12 * 60 * 60); // 6am-12pm
|
||||||
|
|
||||||
private static final Range AFTERNOON_RANGE = new Range(13 * 60 * 60, 17 * 60 * 60); // 1pm-5pm
|
private static final Range AFTERNOON_RANGE = new Range(13 * 60 * 60, 17 * 60 * 60); // 1pm-5pm
|
||||||
|
|
||||||
private static final Range EVENING_RANGE = new Range(17 * 60 * 60, 20 * 60 * 60); // 5pm-8pm
|
private static final Range EVENING_RANGE = new Range(17 * 60 * 60, 20 * 60 * 60); // 5pm-8pm
|
||||||
|
|
||||||
private static final Range NIGHT_RANGE = new Range(20 * 60 * 60, 24 * 60 * 60); // 8pm-12pm
|
private static final Range NIGHT_RANGE = new Range(20 * 60 * 60, 24 * 60 * 60); // 8pm-12pm
|
||||||
|
|
||||||
public EnumRepeaterDayPortion(DayPortion type) {
|
public EnumRepeaterDayPortion(DayPortion type) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.xbib.time.chronic.Range;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class IntegerRepeaterDayPortion extends RepeaterDayPortion<Integer> {
|
public class IntegerRepeaterDayPortion extends RepeaterDayPortion<Integer> {
|
||||||
|
|
||||||
public IntegerRepeaterDayPortion(Integer type) {
|
public IntegerRepeaterDayPortion(Integer type) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum MonthName {
|
|
||||||
ZEROMONTH_DO_NOT_REMOVE,
|
|
||||||
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ package org.xbib.time.chronic.repeaters;
|
||||||
import org.xbib.time.chronic.Options;
|
import org.xbib.time.chronic.Options;
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer;
|
||||||
import org.xbib.time.chronic.tags.Tag;
|
import org.xbib.time.chronic.tags.Tag;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -65,25 +65,25 @@ public abstract class Repeater<T> extends Tag<T> implements Comparable<Repeater<
|
||||||
* @param pointer pointer
|
* @param pointer pointer
|
||||||
* @return span
|
* @return span
|
||||||
*/
|
*/
|
||||||
public Span nextSpan(PointerType pointer) {
|
public Span nextSpan(Pointer.PointerType pointer) {
|
||||||
if (getNow() == null) {
|
if (getNow() == null) {
|
||||||
throw new IllegalStateException("Start point must be set before calling #next");
|
throw new IllegalStateException("Start point must be set before calling #next");
|
||||||
}
|
}
|
||||||
return internalNextSpan(pointer);
|
return internalNextSpan(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Span internalNextSpan(PointerType pointer);
|
protected abstract Span internalNextSpan(Pointer.PointerType pointer);
|
||||||
|
|
||||||
public Span thisSpan(PointerType pointer) {
|
public Span thisSpan(Pointer.PointerType pointer) {
|
||||||
if (getNow() == null) {
|
if (getNow() == null) {
|
||||||
throw new IllegalStateException("Start point must be set before calling #this");
|
throw new IllegalStateException("Start point must be set before calling #this");
|
||||||
}
|
}
|
||||||
return internalThisSpan(pointer);
|
return internalThisSpan(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Span internalThisSpan(PointerType pointer);
|
protected abstract Span internalThisSpan(Pointer.PointerType pointer);
|
||||||
|
|
||||||
public abstract Span getOffset(Span span, int amount, PointerType pointer);
|
public abstract Span getOffset(Span span, int amount, Pointer.PointerType pointer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoField;
|
import java.time.temporal.ChronoField;
|
||||||
|
@ -14,30 +14,18 @@ import java.util.regex.Pattern;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterDayName extends Repeater<DayName> {
|
public class RepeaterDayName extends Repeater<RepeaterDayName.DayName> {
|
||||||
|
|
||||||
private static final int DAY_SECONDS = 86400;
|
private static final int DAY_SECONDS = 86400;
|
||||||
|
|
||||||
private static final Pattern MON_PATTERN = Pattern.compile("^m[ou]n(day)?$");
|
private static final Pattern MON_PATTERN = Pattern.compile("^m[ou]n(day)?$");
|
||||||
|
|
||||||
private static final Pattern TUE_PATTERN = Pattern.compile("^t(ue|eu|oo|u|)s(day)?$");
|
private static final Pattern TUE_PATTERN = Pattern.compile("^t(ue|eu|oo|u|)s(day)?$");
|
||||||
|
|
||||||
private static final Pattern TUE_PATTERN_1 = Pattern.compile("^tue$");
|
private static final Pattern TUE_PATTERN_1 = Pattern.compile("^tue$");
|
||||||
|
|
||||||
private static final Pattern WED_PATTERN_1 = Pattern.compile("^we(dnes|nds|nns)day$");
|
private static final Pattern WED_PATTERN_1 = Pattern.compile("^we(dnes|nds|nns)day$");
|
||||||
|
|
||||||
private static final Pattern WED_PATTERN_2 = Pattern.compile("^wed$");
|
private static final Pattern WED_PATTERN_2 = Pattern.compile("^wed$");
|
||||||
|
|
||||||
private static final Pattern THU_PATTERN_1 = Pattern.compile("^th(urs|ers)day$");
|
private static final Pattern THU_PATTERN_1 = Pattern.compile("^th(urs|ers)day$");
|
||||||
|
|
||||||
private static final Pattern THU_PATTERN_2 = Pattern.compile("^thu$");
|
private static final Pattern THU_PATTERN_2 = Pattern.compile("^thu$");
|
||||||
|
|
||||||
private static final Pattern FRI_PATTERN = Pattern.compile("^fr[iy](day)?$");
|
private static final Pattern FRI_PATTERN = Pattern.compile("^fr[iy](day)?$");
|
||||||
|
|
||||||
private static final Pattern SAT_PATTERN = Pattern.compile("^sat(t?[ue]rday)?$");
|
private static final Pattern SAT_PATTERN = Pattern.compile("^sat(t?[ue]rday)?$");
|
||||||
|
|
||||||
private static final Pattern SUN_PATTERN = Pattern.compile("^su[nm](day)?$");
|
private static final Pattern SUN_PATTERN = Pattern.compile("^su[nm](day)?$");
|
||||||
|
|
||||||
private ZonedDateTime currentDayStart;
|
private ZonedDateTime currentDayStart;
|
||||||
|
|
||||||
public RepeaterDayName(DayName type) {
|
public RepeaterDayName(DayName type) {
|
||||||
|
@ -118,4 +106,10 @@ public class RepeaterDayName extends Repeater<DayName> {
|
||||||
return super.toString() + "-dayname-" + getType();
|
return super.toString() + "-dayname-" + getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum DayName {
|
||||||
|
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package org.xbib.time.chronic.repeaters;
|
||||||
import org.xbib.time.chronic.Range;
|
import org.xbib.time.chronic.Range;
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -18,21 +18,14 @@ import java.util.regex.Pattern;
|
||||||
public abstract class RepeaterDayPortion<T> extends Repeater<T> {
|
public abstract class RepeaterDayPortion<T> extends Repeater<T> {
|
||||||
|
|
||||||
private static final Pattern AM_PATTERN = Pattern.compile("^ams?$");
|
private static final Pattern AM_PATTERN = Pattern.compile("^ams?$");
|
||||||
|
|
||||||
private static final Pattern PM_PATTERN = Pattern.compile("^pms?$");
|
private static final Pattern PM_PATTERN = Pattern.compile("^pms?$");
|
||||||
|
|
||||||
private static final Pattern MORNING_PATTERN = Pattern.compile("^mornings?$");
|
private static final Pattern MORNING_PATTERN = Pattern.compile("^mornings?$");
|
||||||
|
|
||||||
private static final Pattern AFTERNOON_PATTERN = Pattern.compile("^afternoons?$");
|
private static final Pattern AFTERNOON_PATTERN = Pattern.compile("^afternoons?$");
|
||||||
|
|
||||||
private static final Pattern EVENING_PATTERN = Pattern.compile("^evenings?$");
|
private static final Pattern EVENING_PATTERN = Pattern.compile("^evenings?$");
|
||||||
|
|
||||||
private static final Pattern NIGHT_PATTERN = Pattern.compile("^(night|nite)s?$");
|
private static final Pattern NIGHT_PATTERN = Pattern.compile("^(night|nite)s?$");
|
||||||
|
|
||||||
private static final int FULL_DAY_SECONDS = 60 * 60 * 24;
|
private static final int FULL_DAY_SECONDS = 60 * 60 * 24;
|
||||||
|
private Range range;
|
||||||
private final Range range;
|
|
||||||
|
|
||||||
private Span currentSpan;
|
private Span currentSpan;
|
||||||
|
|
||||||
public RepeaterDayPortion(T type) {
|
public RepeaterDayPortion(T type) {
|
||||||
|
@ -156,4 +149,10 @@ public abstract class RepeaterDayPortion<T> extends Repeater<T> {
|
||||||
return super.toString() + "-dayportion-" + getType();
|
return super.toString() + "-dayportion-" + getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum DayPortion {
|
||||||
|
AM, PM, MORNING, AFTERNOON, EVENING, NIGHT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,7 +10,6 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterFortnight extends RepeaterUnit {
|
public class RepeaterFortnight extends RepeaterUnit {
|
||||||
|
|
||||||
public static final int FORTNIGHT_SECONDS = 1209600; // (14 * 24 * 60 * 60)
|
public static final int FORTNIGHT_SECONDS = 1209600; // (14 * 24 * 60 * 60)
|
||||||
|
|
||||||
private ZonedDateTime currentFortnightStart;
|
private ZonedDateTime currentFortnightStart;
|
||||||
|
@ -24,12 +23,12 @@ public class RepeaterFortnight extends RepeaterUnit {
|
||||||
protected Span internalNextSpan(PointerType pointer) {
|
protected Span internalNextSpan(PointerType pointer) {
|
||||||
if (currentFortnightStart == null) {
|
if (currentFortnightStart == null) {
|
||||||
if (pointer == PointerType.FUTURE) {
|
if (pointer == PointerType.FUTURE) {
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
Span nextSundaySpan = sundayRepeater.nextSpan(PointerType.FUTURE);
|
Span nextSundaySpan = sundayRepeater.nextSpan(PointerType.FUTURE);
|
||||||
currentFortnightStart = nextSundaySpan.getBeginCalendar();
|
currentFortnightStart = nextSundaySpan.getBeginCalendar();
|
||||||
} else if (pointer == PointerType.PAST) {
|
} else if (pointer == PointerType.PAST) {
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow().plus(RepeaterDay.DAY_SECONDS, ChronoUnit.SECONDS));
|
sundayRepeater.setNow(getNow().plus(RepeaterDay.DAY_SECONDS, ChronoUnit.SECONDS));
|
||||||
sundayRepeater.nextSpan(PointerType.PAST);
|
sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
sundayRepeater.nextSpan(PointerType.PAST);
|
sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
|
@ -56,7 +55,7 @@ public class RepeaterFortnight extends RepeaterUnit {
|
||||||
Span span;
|
Span span;
|
||||||
if (pointer == PointerType.FUTURE) {
|
if (pointer == PointerType.FUTURE) {
|
||||||
ZonedDateTime thisFortnightStart = ymdh(getNow()).plus(RepeaterHour.HOUR_SECONDS, ChronoUnit.SECONDS);
|
ZonedDateTime thisFortnightStart = ymdh(getNow()).plus(RepeaterHour.HOUR_SECONDS, ChronoUnit.SECONDS);
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
sundayRepeater.thisSpan(PointerType.FUTURE);
|
sundayRepeater.thisSpan(PointerType.FUTURE);
|
||||||
Span thisSundaySpan = sundayRepeater.thisSpan(PointerType.FUTURE);
|
Span thisSundaySpan = sundayRepeater.thisSpan(PointerType.FUTURE);
|
||||||
|
@ -64,7 +63,7 @@ public class RepeaterFortnight extends RepeaterUnit {
|
||||||
span = new Span(thisFortnightStart, thisFortnightEnd);
|
span = new Span(thisFortnightStart, thisFortnightEnd);
|
||||||
} else if (pointer == PointerType.PAST) {
|
} else if (pointer == PointerType.PAST) {
|
||||||
ZonedDateTime thisFortnightEnd = ymdh(getNow());
|
ZonedDateTime thisFortnightEnd = ymdh(getNow());
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
ZonedDateTime thisFortnightStart = lastSundaySpan.getBeginCalendar();
|
ZonedDateTime thisFortnightStart = lastSundaySpan.getBeginCalendar();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,7 +10,6 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterHour extends RepeaterUnit {
|
public class RepeaterHour extends RepeaterUnit {
|
||||||
|
|
||||||
public static final int HOUR_SECONDS = 3600;
|
public static final int HOUR_SECONDS = 3600;
|
||||||
|
|
||||||
private ZonedDateTime currentDayStart;
|
private ZonedDateTime currentDayStart;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,7 +10,6 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterMinute extends RepeaterUnit {
|
public class RepeaterMinute extends RepeaterUnit {
|
||||||
|
|
||||||
public static final int MINUTE_SECONDS = 60;
|
public static final int MINUTE_SECONDS = 60;
|
||||||
|
|
||||||
private ZonedDateTime currentMinuteStart;
|
private ZonedDateTime currentMinuteStart;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,7 +10,6 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterMonth extends RepeaterUnit {
|
public class RepeaterMonth extends RepeaterUnit {
|
||||||
|
|
||||||
private static final int MONTH_SECONDS = 2592000; // 30 * 24 * 60 * 60
|
private static final int MONTH_SECONDS = 2592000; // 30 * 24 * 60 * 60
|
||||||
|
|
||||||
private ZonedDateTime currentMonthStart;
|
private ZonedDateTime currentMonthStart;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -13,34 +13,21 @@ import java.util.regex.Pattern;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterMonthName extends Repeater<MonthName> {
|
public class RepeaterMonthName extends Repeater<RepeaterMonthName.MonthName> {
|
||||||
|
|
||||||
private static final Pattern JAN_PATTERN = Pattern.compile("^jan\\.?(uary)?$");
|
private static final Pattern JAN_PATTERN = Pattern.compile("^jan\\.?(uary)?$");
|
||||||
|
|
||||||
private static final Pattern FEB_PATTERN = Pattern.compile("^feb\\.?(ruary)?$");
|
private static final Pattern FEB_PATTERN = Pattern.compile("^feb\\.?(ruary)?$");
|
||||||
|
|
||||||
private static final Pattern MAR_PATTERN = Pattern.compile("^mar\\.?(ch)?$");
|
private static final Pattern MAR_PATTERN = Pattern.compile("^mar\\.?(ch)?$");
|
||||||
|
|
||||||
private static final Pattern APR_PATTERN = Pattern.compile("^apr\\.?(il)?$");
|
private static final Pattern APR_PATTERN = Pattern.compile("^apr\\.?(il)?$");
|
||||||
|
|
||||||
private static final Pattern MAY_PATTERN = Pattern.compile("^may$");
|
private static final Pattern MAY_PATTERN = Pattern.compile("^may$");
|
||||||
|
|
||||||
private static final Pattern JUN_PATTERN = Pattern.compile("^jun\\.?e?$");
|
private static final Pattern JUN_PATTERN = Pattern.compile("^jun\\.?e?$");
|
||||||
|
|
||||||
private static final Pattern JUL_PATTERN = Pattern.compile("^jul\\.?y?$");
|
private static final Pattern JUL_PATTERN = Pattern.compile("^jul\\.?y?$");
|
||||||
|
|
||||||
private static final Pattern AUG_PATTERN = Pattern.compile("^aug\\.?(ust)?$");
|
private static final Pattern AUG_PATTERN = Pattern.compile("^aug\\.?(ust)?$");
|
||||||
|
|
||||||
private static final Pattern SEP_PATTERN = Pattern.compile("^sep\\.?(t\\.?|tember)?$");
|
private static final Pattern SEP_PATTERN = Pattern.compile("^sep\\.?(t\\.?|tember)?$");
|
||||||
|
|
||||||
private static final Pattern OCT_PATTERN = Pattern.compile("^oct\\.?(ober)?$");
|
private static final Pattern OCT_PATTERN = Pattern.compile("^oct\\.?(ober)?$");
|
||||||
|
|
||||||
private static final Pattern NOV_PATTERN = Pattern.compile("^nov\\.?(ember)?$");
|
private static final Pattern NOV_PATTERN = Pattern.compile("^nov\\.?(ember)?$");
|
||||||
|
|
||||||
private static final Pattern DEC_PATTERN = Pattern.compile("^dec\\.?(ember)?$");
|
private static final Pattern DEC_PATTERN = Pattern.compile("^dec\\.?(ember)?$");
|
||||||
|
|
||||||
private static final int MONTH_SECONDS = 2592000; // 30 * 24 * 60 * 60
|
private static final int MONTH_SECONDS = 2592000; // 30 * 24 * 60 * 60
|
||||||
|
|
||||||
private ZonedDateTime currentMonthBegin;
|
private ZonedDateTime currentMonthBegin;
|
||||||
|
|
||||||
public RepeaterMonthName(MonthName type) {
|
public RepeaterMonthName(MonthName type) {
|
||||||
|
@ -159,4 +146,12 @@ public class RepeaterMonthName extends Repeater<MonthName> {
|
||||||
return super.toString() + "-monthname-" + getType();
|
return super.toString() + "-monthname-" + getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum MonthName {
|
||||||
|
ZEROMONTH_DO_NOT_REMOVE,
|
||||||
|
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,7 +10,6 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterSecond extends RepeaterUnit {
|
public class RepeaterSecond extends RepeaterUnit {
|
||||||
|
|
||||||
private static final int SECOND_SECONDS = 1;
|
private static final int SECOND_SECONDS = 1;
|
||||||
|
|
||||||
private ZonedDateTime secondStart;
|
private ZonedDateTime secondStart;
|
||||||
|
@ -23,6 +22,7 @@ public class RepeaterSecond extends RepeaterUnit {
|
||||||
} else {
|
} else {
|
||||||
secondStart = secondStart.plus(direction, ChronoUnit.SECONDS);
|
secondStart = secondStart.plus(direction, ChronoUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Span(secondStart, ChronoUnit.SECONDS, 1);
|
return new Span(secondStart, ChronoUnit.SECONDS, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.xbib.time.chronic.Options;
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.Tick;
|
import org.xbib.time.chronic.Tick;
|
||||||
import org.xbib.time.chronic.Token;
|
import org.xbib.time.chronic.Token;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -16,17 +16,13 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterTime extends Repeater<Tick> {
|
public class RepeaterTime extends Repeater<Tick> {
|
||||||
|
|
||||||
private static final Pattern TIME_PATTERN = Pattern.compile("^\\d{1,2}(:?\\d{2})?([\\.:]?\\d{2})?$");
|
private static final Pattern TIME_PATTERN = Pattern.compile("^\\d{1,2}(:?\\d{2})?([\\.:]?\\d{2})?$");
|
||||||
|
|
||||||
private ZonedDateTime currentTime;
|
private ZonedDateTime currentTime;
|
||||||
|
|
||||||
public RepeaterTime(String time) {
|
public RepeaterTime(String time) {
|
||||||
super(null);
|
super(null);
|
||||||
String t = time.replaceAll(":", "");
|
String t = time.replaceAll(":", "");
|
||||||
Tick type;
|
Tick type;
|
||||||
boolean ambiguous = time.contains(":") && Integer.parseInt(t.substring(0, 1)) != 0 &&
|
|
||||||
Integer.parseInt(t.substring(0, 2)) <= 12;
|
|
||||||
int length = t.length();
|
int length = t.length();
|
||||||
if (length <= 2) {
|
if (length <= 2) {
|
||||||
int hours = Integer.parseInt(t);
|
int hours = Integer.parseInt(t);
|
||||||
|
@ -41,6 +37,8 @@ public class RepeaterTime extends Repeater<Tick> {
|
||||||
int minutesInSeconds = Integer.parseInt(t.substring(1)) * 60;
|
int minutesInSeconds = Integer.parseInt(t.substring(1)) * 60;
|
||||||
type = new Tick(hoursInSeconds + minutesInSeconds, true);
|
type = new Tick(hoursInSeconds + minutesInSeconds, true);
|
||||||
} else if (length == 4) {
|
} else if (length == 4) {
|
||||||
|
boolean ambiguous = time.contains(":") && Integer.parseInt(t.substring(0, 1)) != 0 &&
|
||||||
|
Integer.parseInt(t.substring(0, 2)) <= 12;
|
||||||
int hours = Integer.parseInt(t.substring(0, 2));
|
int hours = Integer.parseInt(t.substring(0, 2));
|
||||||
int hoursInSeconds = hours * 60 * 60;
|
int hoursInSeconds = hours * 60 * 60;
|
||||||
int minutesInSeconds = Integer.parseInt(t.substring(2)) * 60;
|
int minutesInSeconds = Integer.parseInt(t.substring(2)) * 60;
|
||||||
|
@ -55,6 +53,8 @@ public class RepeaterTime extends Repeater<Tick> {
|
||||||
int seconds = Integer.parseInt(t.substring(3));
|
int seconds = Integer.parseInt(t.substring(3));
|
||||||
type = new Tick(hoursInSeconds + minutesInSeconds + seconds, true);
|
type = new Tick(hoursInSeconds + minutesInSeconds + seconds, true);
|
||||||
} else if (length == 6) {
|
} else if (length == 6) {
|
||||||
|
boolean ambiguous = time.contains(":") && Integer.parseInt(t.substring(0, 1)) != 0 &&
|
||||||
|
Integer.parseInt(t.substring(0, 2)) <= 12;
|
||||||
int hours = Integer.parseInt(t.substring(0, 2));
|
int hours = Integer.parseInt(t.substring(0, 2));
|
||||||
int hoursInSeconds = hours * 60 * 60;
|
int hoursInSeconds = hours * 60 * 60;
|
||||||
int minutesInSeconds = Integer.parseInt(t.substring(2, 4)) * 60;
|
int minutesInSeconds = Integer.parseInt(t.substring(2, 4)) * 60;
|
||||||
|
@ -84,30 +84,29 @@ public class RepeaterTime extends Repeater<Tick> {
|
||||||
private static Integer integerValue(String str) {
|
private static Integer integerValue(String str) {
|
||||||
if (str != null) {
|
if (str != null) {
|
||||||
String s = str.toLowerCase();
|
String s = str.toLowerCase();
|
||||||
switch (s) {
|
if ("one".equals(s)) {
|
||||||
case "one":
|
|
||||||
return 1;
|
return 1;
|
||||||
case "two":
|
} else if ("two".equals(s)) {
|
||||||
return 2;
|
return 2;
|
||||||
case "three":
|
} else if ("three".equals(s)) {
|
||||||
return 3;
|
return 3;
|
||||||
case "four":
|
} else if ("four".equals(s)) {
|
||||||
return 4;
|
return 4;
|
||||||
case "five":
|
} else if ("five".equals(s)) {
|
||||||
return 5;
|
return 5;
|
||||||
case "six":
|
} else if ("six".equals(s)) {
|
||||||
return 6;
|
return 6;
|
||||||
case "seven":
|
} else if ("seven".equals(s)) {
|
||||||
return 7;
|
return 7;
|
||||||
case "eight":
|
} else if ("eight".equals(s)) {
|
||||||
return 8;
|
return 8;
|
||||||
case "nine":
|
} else if ("nine".equals(s)) {
|
||||||
return 9;
|
return 9;
|
||||||
case "ten":
|
} else if ("ten".equals(s)) {
|
||||||
return 10;
|
return 10;
|
||||||
case "eleven":
|
} else if ("eleven".equals(s)) {
|
||||||
return 11;
|
return 11;
|
||||||
case "twelve":
|
} else if ("twelve".equals(s)) {
|
||||||
return 12;
|
return 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,8 +158,8 @@ public class RepeaterTime extends Repeater<Tick> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List<ZonedDateTime> pastDates = new LinkedList<>();
|
|
||||||
if (tick.isAmbiguous()) {
|
if (tick.isAmbiguous()) {
|
||||||
|
List<ZonedDateTime> pastDates = new LinkedList<>();
|
||||||
pastDates.add(midnight.plus(halfDay + (long) tick.intValue(), ChronoUnit.SECONDS));
|
pastDates.add(midnight.plus(halfDay + (long) tick.intValue(), ChronoUnit.SECONDS));
|
||||||
pastDates.add(midnight.plus(tick.intValue(), ChronoUnit.SECONDS));
|
pastDates.add(midnight.plus(tick.intValue(), ChronoUnit.SECONDS));
|
||||||
pastDates.add(yesterdayMidnight.plus(tick.intValue() * 2L, ChronoUnit.SECONDS));
|
pastDates.add(yesterdayMidnight.plus(tick.intValue() * 2L, ChronoUnit.SECONDS));
|
||||||
|
@ -172,6 +171,7 @@ public class RepeaterTime extends Repeater<Tick> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
List<ZonedDateTime> pastDates = new LinkedList<>();
|
||||||
pastDates.add(midnight.plus(tick.intValue(), ChronoUnit.SECONDS));
|
pastDates.add(midnight.plus(tick.intValue(), ChronoUnit.SECONDS));
|
||||||
pastDates.add(yesterdayMidnight.plus(tick.intValue(), ChronoUnit.SECONDS));
|
pastDates.add(yesterdayMidnight.plus(tick.intValue(), ChronoUnit.SECONDS));
|
||||||
for (ZonedDateTime pastDate : pastDates) {
|
for (ZonedDateTime pastDate : pastDates) {
|
||||||
|
@ -183,15 +183,18 @@ public class RepeaterTime extends Repeater<Tick> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!done && currentTime == null) {
|
if (!done && currentTime == null) {
|
||||||
throw new IllegalStateException("Current time cannot be null at this point.");
|
throw new IllegalStateException("Current time cannot be null at this point.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
int increment = tick.isAmbiguous() ? halfDay : fullDay;
|
int increment = tick.isAmbiguous() ? halfDay : fullDay;
|
||||||
long direction = pointer == PointerType.FUTURE ? 1L : -1L;
|
long direction = pointer == PointerType.FUTURE ? 1L : -1L;
|
||||||
currentTime = currentTime.plus(direction * increment, ChronoUnit.SECONDS);
|
currentTime = currentTime.plus(direction * increment, ChronoUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Span(currentTime, currentTime.plus(getWidth(), ChronoUnit.SECONDS));
|
return new Span(currentTime, currentTime.plus(getWidth(), ChronoUnit.SECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,23 +10,14 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class RepeaterUnit extends Repeater<Object> {
|
public abstract class RepeaterUnit extends Repeater<Object> {
|
||||||
|
|
||||||
private static final Pattern YEAR_PATTERN = Pattern.compile("^years?$");
|
private static final Pattern YEAR_PATTERN = Pattern.compile("^years?$");
|
||||||
|
|
||||||
private static final Pattern MONTH_PATTERN = Pattern.compile("^months?$");
|
private static final Pattern MONTH_PATTERN = Pattern.compile("^months?$");
|
||||||
|
|
||||||
private static final Pattern FORTNIGHT_PATTERN = Pattern.compile("^fortnights?$");
|
private static final Pattern FORTNIGHT_PATTERN = Pattern.compile("^fortnights?$");
|
||||||
|
|
||||||
private static final Pattern WEEK_PATTERN = Pattern.compile("^weeks?$");
|
private static final Pattern WEEK_PATTERN = Pattern.compile("^weeks?$");
|
||||||
|
|
||||||
private static final Pattern WEEKEND_PATTERN = Pattern.compile("^weekends?$");
|
private static final Pattern WEEKEND_PATTERN = Pattern.compile("^weekends?$");
|
||||||
|
|
||||||
private static final Pattern DAY_PATTERN = Pattern.compile("^days?$");
|
private static final Pattern DAY_PATTERN = Pattern.compile("^days?$");
|
||||||
|
|
||||||
private static final Pattern HOUR_PATTERN = Pattern.compile("^hours?$");
|
private static final Pattern HOUR_PATTERN = Pattern.compile("^hours?$");
|
||||||
|
|
||||||
private static final Pattern MINUTE_PATTERN = Pattern.compile("^minutes?$");
|
private static final Pattern MINUTE_PATTERN = Pattern.compile("^minutes?$");
|
||||||
|
|
||||||
private static final Pattern SECOND_PATTERN = Pattern.compile("^seconds?$");
|
private static final Pattern SECOND_PATTERN = Pattern.compile("^seconds?$");
|
||||||
|
|
||||||
public RepeaterUnit() {
|
public RepeaterUnit() {
|
||||||
|
@ -52,9 +43,7 @@ public abstract class RepeaterUnit extends Repeater<Object> {
|
||||||
String unitName = unitNameEnum.name();
|
String unitName = unitNameEnum.name();
|
||||||
String capitalizedUnitName = unitName.substring(0, 1) + unitName.substring(1).toLowerCase();
|
String capitalizedUnitName = unitName.substring(0, 1) + unitName.substring(1).toLowerCase();
|
||||||
String repeaterClassName = RepeaterUnit.class.getPackage().getName() + ".Repeater" + capitalizedUnitName;
|
String repeaterClassName = RepeaterUnit.class.getPackage().getName() + ".Repeater" + capitalizedUnitName;
|
||||||
return Class.forName(repeaterClassName)
|
return Class.forName(repeaterClassName).asSubclass(RepeaterUnit.class).newInstance();
|
||||||
.asSubclass(RepeaterUnit.class)
|
|
||||||
.getConstructor().newInstance();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -75,4 +64,10 @@ public abstract class RepeaterUnit extends Repeater<Object> {
|
||||||
((Repeater) other).getNow().equals(getNow());
|
((Repeater) other).getNow().equals(getNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private enum UnitName {
|
||||||
|
YEAR, MONTH, FORTNIGHT, WEEK, WEEKEND, DAY, HOUR, MINUTE, SECOND
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,9 +10,7 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterWeek extends RepeaterUnit {
|
public class RepeaterWeek extends RepeaterUnit {
|
||||||
|
|
||||||
public static final int WEEK_SECONDS = 604800;
|
public static final int WEEK_SECONDS = 604800;
|
||||||
|
|
||||||
public static final int WEEK_DAYS = 7;
|
public static final int WEEK_DAYS = 7;
|
||||||
|
|
||||||
private ZonedDateTime currentWeekStart;
|
private ZonedDateTime currentWeekStart;
|
||||||
|
@ -26,12 +24,12 @@ public class RepeaterWeek extends RepeaterUnit {
|
||||||
protected Span internalNextSpan(PointerType pointer) {
|
protected Span internalNextSpan(PointerType pointer) {
|
||||||
if (currentWeekStart == null) {
|
if (currentWeekStart == null) {
|
||||||
if (pointer == PointerType.FUTURE) {
|
if (pointer == PointerType.FUTURE) {
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
Span nextSundaySpan = sundayRepeater.nextSpan(PointerType.FUTURE);
|
Span nextSundaySpan = sundayRepeater.nextSpan(PointerType.FUTURE);
|
||||||
currentWeekStart = nextSundaySpan.getBeginCalendar();
|
currentWeekStart = nextSundaySpan.getBeginCalendar();
|
||||||
} else if (pointer == PointerType.PAST) {
|
} else if (pointer == PointerType.PAST) {
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow().plus(1, ChronoUnit.DAYS));
|
sundayRepeater.setNow(getNow().plus(1, ChronoUnit.DAYS));
|
||||||
sundayRepeater.nextSpan(PointerType.PAST);
|
sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
|
@ -54,20 +52,20 @@ public class RepeaterWeek extends RepeaterUnit {
|
||||||
ZonedDateTime thisWeekEnd;
|
ZonedDateTime thisWeekEnd;
|
||||||
if (pointer == PointerType.FUTURE) {
|
if (pointer == PointerType.FUTURE) {
|
||||||
thisWeekStart = ymdh(getNow()).plus(1, ChronoUnit.HOURS);
|
thisWeekStart = ymdh(getNow()).plus(1, ChronoUnit.HOURS);
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
Span thisSundaySpan = sundayRepeater.thisSpan(PointerType.FUTURE);
|
Span thisSundaySpan = sundayRepeater.thisSpan(PointerType.FUTURE);
|
||||||
thisWeekEnd = thisSundaySpan.getBeginCalendar();
|
thisWeekEnd = thisSundaySpan.getBeginCalendar();
|
||||||
thisWeekSpan = new Span(thisWeekStart, thisWeekEnd);
|
thisWeekSpan = new Span(thisWeekStart, thisWeekEnd);
|
||||||
} else if (pointer == PointerType.PAST) {
|
} else if (pointer == PointerType.PAST) {
|
||||||
thisWeekEnd = ymdh(getNow());
|
thisWeekEnd = ymdh(getNow());
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
thisWeekStart = lastSundaySpan.getBeginCalendar();
|
thisWeekStart = lastSundaySpan.getBeginCalendar();
|
||||||
thisWeekSpan = new Span(thisWeekStart, thisWeekEnd);
|
thisWeekSpan = new Span(thisWeekStart, thisWeekEnd);
|
||||||
} else if (pointer == PointerType.NONE) {
|
} else if (pointer == PointerType.NONE) {
|
||||||
RepeaterDayName sundayRepeater = new RepeaterDayName(DayName.SUNDAY);
|
RepeaterDayName sundayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SUNDAY);
|
||||||
sundayRepeater.setNow(getNow());
|
sundayRepeater.setNow(getNow());
|
||||||
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
Span lastSundaySpan = sundayRepeater.nextSpan(PointerType.PAST);
|
||||||
thisWeekStart = lastSundaySpan.getBeginCalendar();
|
thisWeekStart = lastSundaySpan.getBeginCalendar();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,8 +10,7 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterWeekend extends RepeaterUnit {
|
public class RepeaterWeekend extends RepeaterUnit {
|
||||||
|
public static final long WEEKEND_SECONDS = 172800L; // (2 * 24 * 60 * 60);
|
||||||
private static final long WEEKEND_SECONDS = 172800L; // (2 * 24 * 60 * 60);
|
|
||||||
|
|
||||||
private ZonedDateTime currentWeekStart;
|
private ZonedDateTime currentWeekStart;
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ public class RepeaterWeekend extends RepeaterUnit {
|
||||||
ZonedDateTime c;
|
ZonedDateTime c;
|
||||||
switch (pointer) {
|
switch (pointer) {
|
||||||
case PAST: {
|
case PAST: {
|
||||||
RepeaterDayName saturdayRepeater = new RepeaterDayName(DayName.SATURDAY);
|
RepeaterDayName saturdayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SATURDAY);
|
||||||
saturdayRepeater.setNow(getNow().plus(RepeaterDay.DAY_SECONDS, ChronoUnit.SECONDS));
|
saturdayRepeater.setNow(getNow().plus(RepeaterDay.DAY_SECONDS, ChronoUnit.SECONDS));
|
||||||
Span lastSaturdaySpan = saturdayRepeater.nextSpan(PointerType.PAST);
|
Span lastSaturdaySpan = saturdayRepeater.nextSpan(PointerType.PAST);
|
||||||
currentWeekStart = lastSaturdaySpan.getBeginCalendar();
|
currentWeekStart = lastSaturdaySpan.getBeginCalendar();
|
||||||
|
@ -34,7 +33,7 @@ public class RepeaterWeekend extends RepeaterUnit {
|
||||||
return new Span(currentWeekStart, c);
|
return new Span(currentWeekStart, c);
|
||||||
}
|
}
|
||||||
case FUTURE: {
|
case FUTURE: {
|
||||||
RepeaterDayName saturdayRepeater = new RepeaterDayName(DayName.SATURDAY);
|
RepeaterDayName saturdayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SATURDAY);
|
||||||
saturdayRepeater.setNow(getNow());
|
saturdayRepeater.setNow(getNow());
|
||||||
Span nextSaturdaySpan = saturdayRepeater.nextSpan(PointerType.FUTURE);
|
Span nextSaturdaySpan = saturdayRepeater.nextSpan(PointerType.FUTURE);
|
||||||
currentWeekStart = nextSaturdaySpan.getBeginCalendar();
|
currentWeekStart = nextSaturdaySpan.getBeginCalendar();
|
||||||
|
@ -51,13 +50,13 @@ public class RepeaterWeekend extends RepeaterUnit {
|
||||||
protected Span internalThisSpan(PointerType pointer) {
|
protected Span internalThisSpan(PointerType pointer) {
|
||||||
Span thisSpan;
|
Span thisSpan;
|
||||||
if (pointer == PointerType.FUTURE || pointer == PointerType.NONE) {
|
if (pointer == PointerType.FUTURE || pointer == PointerType.NONE) {
|
||||||
RepeaterDayName saturdayRepeater = new RepeaterDayName(DayName.SATURDAY);
|
RepeaterDayName saturdayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SATURDAY);
|
||||||
saturdayRepeater.setNow(getNow());
|
saturdayRepeater.setNow(getNow());
|
||||||
Span thisSaturdaySpan = saturdayRepeater.nextSpan(PointerType.FUTURE);
|
Span thisSaturdaySpan = saturdayRepeater.nextSpan(PointerType.FUTURE);
|
||||||
thisSpan = new Span(thisSaturdaySpan.getBeginCalendar(), thisSaturdaySpan.getBeginCalendar()
|
thisSpan = new Span(thisSaturdaySpan.getBeginCalendar(), thisSaturdaySpan.getBeginCalendar()
|
||||||
.plus(RepeaterWeekend.WEEKEND_SECONDS, ChronoUnit.SECONDS));
|
.plus(RepeaterWeekend.WEEKEND_SECONDS, ChronoUnit.SECONDS));
|
||||||
} else if (pointer == PointerType.PAST) {
|
} else if (pointer == PointerType.PAST) {
|
||||||
RepeaterDayName saturdayRepeater = new RepeaterDayName(DayName.SATURDAY);
|
RepeaterDayName saturdayRepeater = new RepeaterDayName(RepeaterDayName.DayName.SATURDAY);
|
||||||
saturdayRepeater.setNow(getNow());
|
saturdayRepeater.setNow(getNow());
|
||||||
Span lastSaturdaySpan = saturdayRepeater.nextSpan(PointerType.PAST);
|
Span lastSaturdaySpan = saturdayRepeater.nextSpan(PointerType.PAST);
|
||||||
thisSpan = new Span(lastSaturdaySpan.getBeginCalendar(), lastSaturdaySpan.getBeginCalendar()
|
thisSpan = new Span(lastSaturdaySpan.getBeginCalendar(), lastSaturdaySpan.getBeginCalendar()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
package org.xbib.time.chronic.repeaters;
|
||||||
|
|
||||||
import org.xbib.time.chronic.Span;
|
import org.xbib.time.chronic.Span;
|
||||||
import org.xbib.time.chronic.tags.PointerType;
|
import org.xbib.time.chronic.tags.Pointer.PointerType;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -10,7 +10,6 @@ import java.time.temporal.ChronoUnit;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RepeaterYear extends RepeaterUnit {
|
public class RepeaterYear extends RepeaterUnit {
|
||||||
|
|
||||||
private ZonedDateTime currentYearStart;
|
private ZonedDateTime currentYearStart;
|
||||||
|
|
||||||
private static ZonedDateTime ymd(ZonedDateTime zonedDateTime) {
|
private static ZonedDateTime ymd(ZonedDateTime zonedDateTime) {
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.time.chronic.repeaters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum UnitName {
|
|
||||||
YEAR, MONTH, FORTNIGHT, WEEK, WEEKEND, DAY, HOUR, MINUTE, SECOND
|
|
||||||
}
|
|
|
@ -11,12 +11,9 @@ import java.util.regex.Pattern;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Grabber extends Tag<Relative> {
|
public class Grabber extends Tag<Grabber.Relative> {
|
||||||
|
|
||||||
private static final Pattern THIS_PATTERN = Pattern.compile("this");
|
private static final Pattern THIS_PATTERN = Pattern.compile("this");
|
||||||
|
|
||||||
private static final Pattern NEXT_PATTERN = Pattern.compile("next");
|
private static final Pattern NEXT_PATTERN = Pattern.compile("next");
|
||||||
|
|
||||||
private static final Pattern LAST_PATTERN = Pattern.compile("last");
|
private static final Pattern LAST_PATTERN = Pattern.compile("last");
|
||||||
|
|
||||||
public Grabber(Relative type) {
|
public Grabber(Relative type) {
|
||||||
|
@ -52,4 +49,10 @@ public class Grabber extends Tag<Relative> {
|
||||||
return "grabber-" + getType();
|
return "grabber-" + getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum Relative {
|
||||||
|
LAST, NEXT, THIS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class Ordinal extends Tag<Integer> {
|
||||||
|
|
||||||
static final Pattern ORDINAL_PATTERN = Pattern.compile("^(\\d*)(st|nd|rd|th)$");
|
static final Pattern ORDINAL_PATTERN = Pattern.compile("^(\\d*)(st|nd|rd|th)$");
|
||||||
|
|
||||||
protected Ordinal(Integer type) {
|
Ordinal(Integer type) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,7 @@ import java.util.regex.Matcher;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class OrdinalDay extends Ordinal {
|
public class OrdinalDay extends Ordinal {
|
||||||
|
public OrdinalDay(Integer type) {
|
||||||
private OrdinalDay(Integer type) {
|
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import java.util.regex.Pattern;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Pointer extends Tag<PointerType> {
|
public class Pointer extends Tag<Pointer.PointerType> {
|
||||||
|
|
||||||
private static final Pattern IN_PATTERN = Pattern.compile("\\bin\\b");
|
private static final Pattern IN_PATTERN = Pattern.compile("\\bin\\b");
|
||||||
|
|
||||||
|
@ -52,4 +52,10 @@ public class Pointer extends Tag<PointerType> {
|
||||||
return "pointer-" + getType();
|
return "pointer-" + getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum PointerType {
|
||||||
|
PAST, FUTURE, NONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.time.chronic.tags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum PointerType {
|
|
||||||
PAST, FUTURE, NONE
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.time.chronic.tags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum Relative {
|
|
||||||
LAST, NEXT, THIS
|
|
||||||
}
|
|
|
@ -13,9 +13,8 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Scalar extends Tag<Integer> {
|
public class Scalar extends Tag<Integer> {
|
||||||
|
static final Set<String> TIMES =
|
||||||
protected static final Set<String> TIMES = new HashSet<>(Arrays.asList("am", "pm", "morning", "afternoon", "evening", "night"));
|
new HashSet<>(Arrays.asList("am", "pm", "morning", "afternoon", "evening", "night"));
|
||||||
|
|
||||||
private static final Pattern SCALAR_PATTERN = Pattern.compile("^\\d*$");
|
private static final Pattern SCALAR_PATTERN = Pattern.compile("^\\d*$");
|
||||||
|
|
||||||
public Scalar(Integer type) {
|
public Scalar(Integer type) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ScalarDay extends Scalar {
|
public class ScalarDay extends Scalar {
|
||||||
|
|
||||||
private static final Pattern DAY_PATTERN = Pattern.compile("^\\d\\d?$");
|
private static final Pattern DAY_PATTERN = Pattern.compile("^\\d\\d?$");
|
||||||
|
|
||||||
public ScalarDay(Integer type) {
|
public ScalarDay(Integer type) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ScalarMonth extends Scalar {
|
public class ScalarMonth extends Scalar {
|
||||||
|
|
||||||
private static final Pattern MONTH_PATTERN = Pattern.compile("^\\d\\d?$");
|
private static final Pattern MONTH_PATTERN = Pattern.compile("^\\d\\d?$");
|
||||||
|
|
||||||
public ScalarMonth(Integer type) {
|
public ScalarMonth(Integer type) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ScalarYear extends Scalar {
|
public class ScalarYear extends Scalar {
|
||||||
|
|
||||||
private static final Pattern YEAR_PATTERN = Pattern.compile("^([1-9]\\d)?\\d\\d?$");
|
private static final Pattern YEAR_PATTERN = Pattern.compile("^([1-9]\\d)?\\d\\d?$");
|
||||||
|
|
||||||
private ScalarYear(Integer type) {
|
private ScalarYear(Integer type) {
|
||||||
|
|
|
@ -8,9 +8,9 @@ import java.util.List;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Separator extends Tag<SeparatorType> {
|
public class Separator extends Tag<Separator.SeparatorType> {
|
||||||
|
|
||||||
public Separator(SeparatorType type) {
|
Separator(SeparatorType type) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,4 +42,10 @@ public class Separator extends Tag<SeparatorType> {
|
||||||
return "separator";
|
return "separator";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum SeparatorType {
|
||||||
|
COMMA, DASH, SLASH, AT, IN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SeparatorAt extends Separator {
|
public class SeparatorAt extends Separator {
|
||||||
|
|
||||||
private static final Pattern AT_PATTERN = Pattern.compile("^(at|@)$");
|
private static final Pattern AT_PATTERN = Pattern.compile("^(at|@)$");
|
||||||
|
|
||||||
private SeparatorAt(SeparatorType type) {
|
private SeparatorAt(SeparatorType type) {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SeparatorComma extends Separator {
|
public class SeparatorComma extends Separator {
|
||||||
|
|
||||||
private static final Pattern COMMA_PATTERN = Pattern.compile("^,$");
|
private static final Pattern COMMA_PATTERN = Pattern.compile("^,$");
|
||||||
|
|
||||||
private SeparatorComma(SeparatorType type) {
|
private SeparatorComma(SeparatorType type) {
|
||||||
|
|
|
@ -11,9 +11,7 @@ import java.util.regex.Pattern;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SeparatorSlashOrDash extends Separator {
|
public class SeparatorSlashOrDash extends Separator {
|
||||||
|
|
||||||
private static final Pattern SLASH_PATTERN = Pattern.compile("^/$");
|
private static final Pattern SLASH_PATTERN = Pattern.compile("^/$");
|
||||||
|
|
||||||
private static final Pattern DASH_PATTERN = Pattern.compile("^-$");
|
private static final Pattern DASH_PATTERN = Pattern.compile("^-$");
|
||||||
|
|
||||||
public SeparatorSlashOrDash(SeparatorType type) {
|
public SeparatorSlashOrDash(SeparatorType type) {
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.time.chronic.tags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public enum SeparatorType {
|
|
||||||
COMMA, DASH, SLASH, AT, IN
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ package org.xbib.time.chronic.tags;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StringTag extends Tag<String> {
|
public class StringTag extends Tag<String> {
|
||||||
|
|
||||||
public StringTag(String type) {
|
public StringTag(String type) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue