From c459048a6d35bd99ab1fe3416cbe29363fa8fdd8 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 27 Apr 2022 15:31:27 +0200 Subject: [PATCH 01/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide - Added an initial maintainer guide with release instructions and trying if this can be published via Jenkins --- Jenkinsfile | 12 +- aggregate-uimaj-docbooks/pom.xml | 1 + uima-doc-v3-maintainers-guide/pom.xml | 155 ++++++ .../src/docs/asciidoc/common_book_info.adoc | 42 ++ .../src/docs/asciidoc/uv3.release.adoc | 477 ++++++++++++++++++ .../asciidoc/version_3_maintainers_guide.adoc | 28 + uima-doc-v3-users-guide/pom.xml | 2 +- .../docs/asciidoc/version_3_users_guide.adoc | 2 +- 8 files changed, 716 insertions(+), 3 deletions(-) create mode 100644 uima-doc-v3-maintainers-guide/pom.xml create mode 100644 uima-doc-v3-maintainers-guide/src/docs/asciidoc/common_book_info.adoc create mode 100644 uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc create mode 100644 uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc diff --git a/Jenkinsfile b/Jenkinsfile index 7d2ed34788..1b285b3590 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,10 +15,20 @@ // specific language governing permissions and limitations // under the License. -@Library('uima-build-jenkins-shared-library') _ +@Library('uima-build-jenkins-shared-library@feature/UIMA-6437-Allow-publishing-HTML-documentation-from-Jenkinsfile') _ defaultPipeline { // The Eclipse libraries that our plugins depend unfortunately on required Java 11 jdk = 'jdk_11_latest' extraMavenArguments = '-Pjacoco,pmd,run-rat-report' + documentation = [[ + allowMissing: false, + alwaysLinkToLastBuild: true, + keepAll: false, + reportDir: 'uima-doc-v3-maintainers-guide/target/site/d', + includes: '**/*', + reportFiles: 'version_3_maintainers_guide.html', + reportName: 'Maintainers Guide', + reportTitles: 'Maintainers Guide' + ]] } diff --git a/aggregate-uimaj-docbooks/pom.xml b/aggregate-uimaj-docbooks/pom.xml index 2f10b1d05e..480721d60a 100644 --- a/aggregate-uimaj-docbooks/pom.xml +++ b/aggregate-uimaj-docbooks/pom.xml @@ -70,5 +70,6 @@ ../uima-docbook-tutorials-and-users-guides ../uima-doc-v3-users-guide + ../uima-doc-v3-maintainers-guide \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/pom.xml b/uima-doc-v3-maintainers-guide/pom.xml new file mode 100644 index 0000000000..33adbe7f6a --- /dev/null +++ b/uima-doc-v3-maintainers-guide/pom.xml @@ -0,0 +1,155 @@ + + + + 4.0.0 + + + org.apache.uima + uimaj-parent + 3.3.0-SNAPSHOT + ../uimaj-parent/pom.xml + + + uima-doc-v3-maintainers-guide + pom + Apache UIMA SDK Documentation - Version 3 Maintainer's Guide + ${uimaWebsiteUrl} + + + 2.1.0 + 2.4.2 + 1.5.4 + + + + + + org.asciidoctor + asciidoctor-maven-plugin + ${asciidoctor.plugin.version} + + + user-guide-html + generate-resources + + process-asciidoc + + + html5 + + left + + + + + user-guide-pdf + generate-resources + + process-asciidoc + + + pdf + + preamble + + + + + + version_3_maintainers_guide.adoc + ${project.build.directory}/site/d + + book + 8 + true + true + ${project.version} + ${project.version} + Apache UIMA Version 3 Maintainer's Guide + https://uima.apache.org + font + true + + + asciidoctor-pdf + + + + + org.asciidoctor + asciidoctorj + ${asciidoctor.version} + + + org.asciidoctor + asciidoctorj-pdf + ${asciidoctor.pdf.version} + + + + + + + + m2e + + + m2e.version + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.asciidoctor + asciidoctor-maven-plugin + [1.0,) + + process-asciidoc + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/common_book_info.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/common_book_info.adoc new file mode 100644 index 0000000000..537f3e60d0 --- /dev/null +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/common_book_info.adoc @@ -0,0 +1,42 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + +Copyright © 2006, 2021 The Apache Software Foundation + +Copyright © 2004, 2006 International Business Machines Corporation + +[discrete] +=== License and Disclaimer + +The ASF licenses this documentation to you under the Apache License, Version 2.0 (the "License"); +you may not use this documentation except in compliance with the License. You may obtain a copy of +the License at + +[.text-center] +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, this documentation and its contents are +distributed under the License 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. + +[discrete] +=== Trademarks + +All terms mentioned in the text that are known to be trademarks or service marks have been +appropriately capitalized. Use of such terms in this book should not be regarded as affecting the +validity of the the trademark or service mark. \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc new file mode 100644 index 0000000000..a025adfad0 --- /dev/null +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -0,0 +1,477 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + += UIMA Release Process + +The Apache UIMA project mainly releases: + +* Sub-projects like Apache UIMA Java SDK, uimaFIT, RUTA etc. +* Some Maven build tooling components that need to be in the Maven repositories to support our Maven processes. + +Releases show up in the Maven central repository and/or as downloadable artifacts listed on our downloads pages. + +== Release planning + +Release planning happens in the issue tracker: + +* link:https://issues.apache.org/jira/projects/UIMA/[Apache UIMA Issue Tracker] + +As part of the planning, new issues are created and typically one somebody assigns the issue to themselves, they also set target version to the next bugfix or feature release in line. + +There is no fixed release schedule. Anybody may ask for the preparation of a new release. A committer then has to step up to act as the release manager and to perform the release process. + +== Maintainer one-time setup + +FIXME: link:https://uima.apache.org/one-time-release-setup.html[old website] + +== Performing the release + +* {empty} ++ +.Create release issue and release preparation branch +[%collapsible] +==== +Our development branches (i.e. `main` and `maintenance/*`) should be protected, so you cannot run a release directly on them. So in order to start a release, first create a release issue to track the release progress and then a corresponding release preparation branch in the repository. Release preparation branches for feature releases should be based off `main` whereas branches for preparing bugfix releases should be based off a `maintenance/XXX` branch. Once the release vote is complete, the preparation branch is then merged just like any other pull request. +==== +* {empty} ++ +.Update `README` file +[%collapsible] +==== +Make sure that any README files have been updated with the latest release information and release numbers. +==== +* {empty} ++ +.Update `RELEASE_NOTES.md` file +[%collapsible] +==== +Update the release notes for the release. In particular, include the notable changes (typically all features and bug fixes). You can use this list later for the release announcement mail as well. + +Also mention any important changes regarding backwards compatibility. +==== +* {empty} ++ +.Check the `LICENSE` and `NOTICE` files for the binary release +[%collapsible] +==== +There may be a `[project-root]/src/main/bin_distr_license_notices` folder containing `LICENSE` and `NOTICE` files which are used for preparing the binary release packages. If the release includes new or updated dependencies bundled in the binary release packages, then these files need to be updated with the respective content from the `LICENSE` and `NOTICE` files that may be present in these bundled dependencies (inside the JARs going to the `lib`) folder. +==== +* {empty} ++ +.Make sure to remove all SNAPSHOT repositories and SNAPSHOT dependencies +[%collapsible] +==== +The Maven release plugin will complain if there are still any `SNAPSHOT` dependencies being referenced that are not part of the release. However, it will **NOT** complain if there are still Maven SNAPSHOT repository declarations in the POMs. Check in particular the parent pom for SNAPSHOT repositories and comment them out or remove them. +==== +* {empty} ++ +.Update Jira version in POM for fixed-issues report +[%collapsible] +==== +Edit the POM of the top level thing being released, to add the property: + +2.10.2SDK + +replacing the 2.10.2SDK with the actual Jira version name for the Jira release being done. This value is used during release processing to automatically generate a report of the list of Jira issues that are included in this release. Change "2.10.2SDK"" to be the actual jira version name, which you can get from the Jira url by going to https://issues.apache.org/jira/browse/UIMA and selecting "Releases" and then going to the particular version and copying its name. + +You can also generate this report manually (for instance, if you want to have a look at what it will produce) by going to top level project being released (e.g., uimaj-distr) and issuing the maven command: + +mvn changes:jira-report -N + +Each time this plugin is run, it creates an updated report in the top level of this project. This report doesn't need to be checked into source control. It will be regenerated and copied into the distribution archives (source and binary) during a release. The RELEASE_NOTES.html files have been updated to refer to this generated report. + +Running the mvn release... command will cause this report to be generated or updated, every time the command is run. So it is important that the POM is updated to include the internal Jira version number, so the right report is generated. +==== +* {empty} ++ +.Update API comparison version in POM +[%collapsible] +==== +Update the parent-pom settings for API change reports setting `api_check_old_version` to the correct previous version to use. +==== +* {empty} ++ +.Clean local m2 repository +[%collapsible] +==== +Purge your local maven repository of artifacts being built by running in the top level directory you'll be building from: + +mvn dependency:purge-local-repository + +Note that this will immediately re-resolve the dependencies from the maven repositories you have configured. + +For many multi-module projects, this will fail because it purges things that other modules need. So, the alternative is to just delete the .m2/.../uima/... directory on your build machine. +==== +* {empty} ++ +.Run a trial build locally with `-Papache-release` +[%collapsible] +==== +Do a trial build of the release candidate: + + $ cd YOUR-BUILD-DIRECTORY + $ mvn clean install -Papache-release + +The `-Papache-release` is used to have the build mimic the build actions that would be taken when the release plugin is running the release build. +==== +* {empty} ++ +.Check the issues report in `issuesFixed` if it looks ok +[%collapsible] +==== +The build includes a generated set of Jira issues fixed (closed or resolved) in this release. To make this accurate, go through the Jiras and ensure the ones you are including in the release are closed/resolved, and that the "Fixed in release xxx" is set for each Jira issue that is part of the release. + +There is a saved "filter" you can adjust for this that will display all fixed Jira issues with no Fixed in release xxx assigned. You can go through subsets of this (use the filter to pick the subset you want) and do "bulk Jira changes" to update multiples of these in parallel, if that makes sense. +==== +* {empty} ++ +.Check that the Eclipse `.classpath` files which are checked in as part of the examples have the proper version numbers for their JARs +[%collapsible] +==== +If the release includes Eclipse projects as examples and the release includes also new or updated dependencies, the Eclipse `.classpath` files in the example projects may need to be updated to include the new libraries. + +NOTE: There may be a generation process involved. E.g. in the UIMA Java SDK, the template for the `.classpath` files can be found in `uimaj-examples/src/main/eclipseProject/classpath`. +==== +* {empty} ++ +.Commit all changes and check out in a new clean build location +[%collapsible] +==== +Make sure all changes are checked into source control. Then checkout (not export) from source control the project(s) you'll be building, into a new *build* location, and do all the building from there. + +If you instead choose to build from your *working* source control checkout, insure it's up-to-date with all changes that others may have checked into the release branch. +==== +* {empty} ++ +.Do the release build (`mvn -DautoVersionSubmodules=true release:prepare release:perform`) +[%collapsible] +==== +We use the `maven-release-plugin` to do the releasing. In the prepare phase, it updates the trunk artifacts to remove the `-SNAPSHOT` suffix, commits it to trunk, and then does an SVN copy or GIT Branch of the trunk or master to create the tag. Then it updates the trunk artifacts to the next version-SNAPSHOT, and commits that. + +The `release:perform` goal checks out the tag and builds/tests/installs and deploys it to the NEXUS staging repository. + +During `release:prepare`, the release plugin asks what the next levels should be and what the tag name should be, and unless there's a good reason, we take the defaults (by just hitting enter). + +When releasing a multi-module project where all the submodules have the same release version as the root project (e.g., uimaj-distr), you can have the release plugin set the version for all the submodules the same value as the root, automatically, just use this form of the `release:prepare`: + +``` +$ mvn release:prepare -DautoVersionSubmodules +``` + +In the past, we added a suffix representing the release candidate to the tag, e.g. `-rc1` for release candidate 1, etc. However, the URL for this tag becomes part of the released POM. After a successful vote, we would have upgraded the release candidate to the final release by renaming the tag in source control. At that point, the URL in the POM would have become invalid. For this reason, it was decided to **NOT** add the `-rc1` to the tag anymore. + +The release plugin automatically signs everything that needs signing using gpg. It also builds the sources.jar, and one overall (for multi-module projects) source-release.zip file, which can be later obtained and should be an (approximate) copy of the tag for that artifact, and once unzipped, should be buildable, using `mvn install`. + +Normally, everything built is uploaded to the Apache's Nexus Staging repository. However, for the (large) distribution objects, such as the source and binary distributions for UIMA Java SDK etc., the "deploy" step is skipped. These artifacts, instead of being "distributed" using the Maven central repository, are distributed using the Apache Mirroring System. + +POMs can refer to other artifacts in several ways, for example via the `` element, or via a `` element. Often, a release will involve releasing together multiple modules (all at `-SNAPSHOT` levels) that refer to one another using these elements. When that happens, the references in these two elements are automatically updated during the release process, from `xx-SNAPSHOT` to `xx` for the tag, and then to the next development level, for the trunk. + +Exception to this: `-SNAPSHOT` suffixes are not updated for references within plugins. + +Note that any JARs, Zips, Tars, tar.gz artifacts must be signed by the Release Manager. When `-Papache-release` is active, the GPG Maven Plugin runs and signs the artifacts with the user's default GPG key. If you have multiple keys on your system, make sure to switch default to the right key before the release. +==== +* {empty} ++ +.Close the staging repository at http://repository.apache.org/ +[%collapsible] +==== +You can upload to the Nexus Staging repository several independent artifacts; they will all get added to the same unique temporary staging repository Nexus creates. Once all the artifacts are in place, you log into https://repository.apache.org using your ASF LDAP credentials, go to your staging repository, and **close** the repository. After that, nothing more can be added. If you deploy another artifact, it will create a new staging repository. + +NOTE: If you **forget to close the repo**, it will be open when you do your next release candidate, and then you'll have in the repo both release candidates, (with later files overwriting newer), which if any file names have changed, will **create a mess.** So be sure to **close** (and **drop** as appropriate) any previous repo +before starting a `release:perform` for a new release candidate, so they deploy into a *fresh* empty staging repo. + +If you have several artifacts to release, and you want subsequent artifacts to depend on the released versions of earlier ones, you can do this, by releasing the first one, then releasing subsequent ones that depend on that, etc. This works because the first one you release will get built with the release version and installed to your local repository, as well as the Nexus staging repository. So subsequent ones that depend on the release version of previous ones, will find that in your local repository. + +If you forget something and close the staging repository too soon, just continue as if you hadn't. Subsequent release artifacts will go into another newly created staging spot on Nexus. The downside of this is that you'll have to tell the *voters* about multiple staging repos. +==== +* {empty} ++ +.Upload artifacts from `target/checkout/target` to a subdirectory of the release staging spot +[%collapsible] +==== +We have a spot at https://dist.apache.org/repos/dist/dev/uima/ for all the artifacts to be released via the Apache mirror system. This is where you put the release candidates. + +Be sure to copy artifacts from the build-from tag spot, which should have a path like: `...[top level project]/target/checkout/target`. Note this is **NOT** from `[top level project]/target`. Doing this will guarantee that you're posting the artifacts built from the tag (which could be different from the `release:prepare` build in /target if someone snuck in a svn commit at the right moment.) + +Copy any artifacts (together with their signings) to the staging spot. A suggested approach: Make a new dir in the build project, called svnUpload (or whatever), and copy the artifacts (from the `...[top level project]/target/checkout/target` directory!) (typically the bin/zip/tar and the source release and all the signature/checksums) into this dir. Then do the svn command: + +``` +$ cd the-svnUpload-directory +$ svn import -m "commit msg, e.g. uimaj-2.8.0 rc5" . https://dist.apache.org/repos/dist/dev/uima/uimaj/n.n.n-rc1/artifacts +``` + +Do not add files like POMs which have line-endings, if they have signatures; the files added should be "binary" style files. (The line endings (if you build on windows) will be changed upon upload to svn, which will result in bad signatures). +==== +* {empty} ++ +.Update the version in the `uimaj-eclipse-update-site` +[%collapsible] +==== +FIXME: Eclipse update site process needs updating... + +For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. +==== +* {empty} ++ +.Set `dropPrevVersions` to `true` in the `uimaj-eclipse-update-site` POM +[%collapsible] +==== +FIXME: Eclipse update site process needs updating... + +For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. +==== +* {empty} ++ +.Build the `uimaj-eclipse-update-site` module with {{-Papache-release}} +[%collapsible] +==== +FIXME: needs update! + +For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. + +The component being released, if it has Eclipse features, will have its own Eclipse update (sub) site, which should be built along with the normal build of the entire component, as part of that component's release. + +In building that component's update site, you may need to edit/update the affected component's feature project(s), and the category.xml file in the update-site, before building it. For releases, run the signEclipseUpdateSite.sh (on Windows - inside Cygwin) to sign the Jars. (Optional:) There's also a verifySignsEclipseUpdateSite.sh you can run to verify the signing was successful. + +If a new Eclipse update site is being added to the composite, edit in the composite project (.../build/uima-eclipse-composite-update-site) the buildCompositeRepository.xml file to add the new update site. If doing a release, run the signing script for the composite site too. + +The actual creation of the update site is done in several steps, following the conventions to link:https://uima.apache.org/saving-svn-resources.html[save SVN resources]. The Maven build for Eclipse update sites will end up with files in .../target/eclipse-update-site/[subsite] which should be copied to some accessible spot for Voting/ testing. (After the vot passes, the files in the target site can be svn switched to the release directory and committed.) + +Test the result: using the extended composite repository in various versions of Eclipse, and verify it installs OK. + +If you changed the composite site, bump up the version of .../build/uima-eclipse-composite-site/pom.xml and commit project changes to the trunk, and tag it. The component's individual update sites should be built and tagged as part of that project's release. +==== +* {empty} ++ +.Upload the update site to a subdirectory of the release staging spot and *commit* (*Caution:* the update site contains a `.svn` folder that needs to be removed!) +[%collapsible] +==== +FIXME: Eclipse update site process needs updating... + +For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. +==== +* {empty} ++ +.Call for a vote on the developer mailing list using the email template below +[%collapsible] +==== +The release candidate typically consists of + +* assembly source and binary distributions, +* the associated source control tag, and +* the individual Maven module artifacts. + +The source and binary distributions are manually copied by the release manager to the Apache distribution SVN in the dev/uima spot, to make them available for review. The Maven module artifacts are found in the Nexus staging repository, and are available once the release manager "closes" the repository. + +After things are staged, you write a note to the dev list, asking for an approval vote. You need to provide the url(s) of the closed staging repository in the note so the approvers can find the code to check, the source control tag corresponding to the release, and if needed, and the place in the distribution SVN where the source and binary distributions being proposed are found. The [VOTE] email should be based on similar previous votes, and include instructions to testers on how to set up their maven settings.xml file to specify the particular staging repository (or repositories, if more than one is being used). + +.Release candidate vote email template +---- +Subject: [VOTE] UIMA Java SDK X.Y.Z RC-N + +Hi, + +the Apache UIMA Java SDK X.Y.Z RC N has been staged. + +This is a bugfix / feature release. + +__Paste list of issues from the RELEASE_NOTES file here__ + +Issues: https://issues.apache.org/jira/issues/?jql=project%20%3D%20UIMA%20AND%20fixVersion%20%3D%20X.Z.YSDK +Dist. artifacts: https://dist.apache.org/repos/dist/dev/uima/uima-uimaj-X.Z.Y-RC-N/ +Eclipse Update Site: https://dist.apache.org/repos/dist/dev/uima/uima-uimaj-X.Z.Y-RC-N/eclipse-update-site-v3/uimaj/ +Maven staging repo: https://repository.apache.org/content/repositories/orgapacheuima-1268 +GitHub tag: https://github.com/apache/uima-uimaj/tree/uimaj-X.Z.Y + +Please vote on release: + +[ ] +1 OK to release +[ ] 0 Don't care +[ ] -1 Not OK to release, because ... + +Thanks. + +-- __Release manager name__ +---- +==== +* {empty} ++ +.VOTE (wait at least for 72 hours, at least 3 +1 votes required for release) +[%collapsible] +==== +See also https://www.apache.org/foundation/voting.html +==== +* {empty} ++ +.Post vote results to the developer mailing list (sign mail using same GPG key that was used to sign release) +[%collapsible] +==== +.Example vote results mail +---- +Subject: [RESULT][VOTE] UIMA Java SDK X.Y.Z RC-N + +Hi all, + +the vote passes, with X +1 and no other votes received. + ++1 Person A ++1 Person B ++1 Person C +... + +No other votes received. + +Thanks to all who voted! + +-- __Release manager name__ +---- +==== +* {empty} ++ +.Copy the release artifacts from the staging spot to the dist spot in SVN +[%collapsible] +==== +The staging spot and the release spot are in the same (large) ASF Subversion repository. So instead of uploading the artifacts again, we can simply copy them from the staging spot at https://dist.apache.org/repos/dist/dev/uima/ to the proper locations under https://dist.apache.org/repos/dist/release/uima/. + +Note that the Eclipse Update Site which was a subfolder in the staging spot must now be copied to the proper location in the P2 composite update site. +==== +* {empty} ++ +.Copy existing Eclipse update site to the archive spot +[%collapsible] +==== +``` +svn copy -m "create eclipse plugin archive for uimaj-3.0.0-3.2.0" https://dist.apache.org/repos/dist/release/uima/eclipse-update-site-v3/uimaj https://dist.apache.org/repos/dist/release/uima/archive-eclipse-update-site/uimaj-3.0.0-3.2.0 +``` +==== +* {empty} ++ +.Delete existing Eclipse update site +[%collapsible] +==== +``` +svn delete -m "reset main Eclipse update subsite for uimaj - delete old one" https://dist.apache.org/repos/dist/release/uima/eclipse-update-site-v3/uimaj +``` +==== +* {empty} ++ +.Remove the old update site and move the new one at https://dist.apache.org/repos/dist/release/uima/eclipse-update-site-v3 +[%collapsible] +==== +``` +svn delete -m "reset main Eclipse update subsite for uimaj - delete old one" https://dist.apache.org/repos/dist/release/uima/eclipse-update-site-v3/uimaj +``` +==== +* {empty} ++ +.Release staging repository at http://repository.apache.org/ +[%collapsible] +==== +``` +Promote the release(s) from the staging repositories: log on to the staging repository again, and release the staged artifacts. This will make the artifacts available in the Maven Central repository. +``` +==== +* {empty} ++ +.Create a new git tag e.g. `rel/uimaj-3.2.0` and remove the one not prefixed with `rel` +[%collapsible] +==== +Tags starting with `rel/` should be protected in all Apache UIMA git repositories. By prefixing the release tag with `rel/`, you make sure the tag cannot be accidentally deleted. +==== +* {empty} ++ +.Merge the release preparation pull request +[%collapsible] +==== +Merge the release preparation pull request just like any other PR via the GitHub website. +==== +* {empty} ++ +.Update website +[%collapsible] +==== +Update the download page of the UIMA website to make the new release artifacts available. This is done indirectly, by editing both the `downloads.xml` page and also by adding entries to the `xdocs/stylesheets/project.xml` page - follow the previous examples. + +Also, things not needed to be mirrored go into our website: in the `docs/d` directory. Currently, this includes `the RELEASE_NOTES` (plus `issuesFixed`) for the release, the new documentation, and the Javadocs. + +Copy `RELEASE_NOTES` and `issuesFixed` from the top level project (where the mvn `release:perform` was done from) in the directory `target/checkout/` ... to the the website in `docs/d/[project-version]`. + +Our main UIMA website has a **News** section that should be updated with news of the release. There are 2 place to update: One is the `index.xml` file, which has a one-line summary (at the bottom) that references a link within the `new.xml` page; and a new entry in the `news.xml` page itself. Follow previous examples. +==== +* {empty} ++ +.Close the release in the issue tracker +[%collapsible] +==== +Update Jira version info to reflect the release status and date +==== +* {empty} ++ +.Post release announcement to `announce@apache.org` (Cc: `dev@uima.apache.org`, `user@uima.apache.org` -- once release has arrived at https://repo1.maven.org/maven2/org/apache/uima/uimaj-core/ -- sign mail using same GPG key that was used to sign release) +[%collapsible] +==== +After release appears on maven central, post an appropriate announce letter. + +To announce the published release send and email to + +* `announce@apache.org` +* `user@uima.apache.org` + +and describe the major changes of the release. Announcements should be posted from the release manager's `@apache.org` address, and signed by the release manager using the same code-signing key as was used to sign the release. For more details please refer to link:https://incubator.apache.org/guides/releasemanagement.html#announcements[A Guide To Release Management During Incubation]. +==== + +== Re-doing a release randidate + +There are two ways to reset things back so you can do another release candidate; depending on how far through the release process you've progressed. + +If you've just done `release:prepare`, you can reset things back to as they were before that command by issuing `mvn release:rollback`. + +Check to confirm that the source control tag for the release candidate is deleted; if not, remove it manually. + +If you've done a `release:perform`, to reset the source, try doing the `release:rollback`; this may work if you haven't done a `release:clean`. + +Otherwise, you have to manually change the `x.y.z-SNAPSHOT` back to their previous value. You can use Eclipse's search/replace to do this, or the mvn versions plugin. + +If a Nexus staging repo was already created, drop it. + +== Preparing the next development cycle + +* Consider updating dependencies and plugins as necessary +** `mvn versions:display-dependency-updates` +** `mvn versions:display-plugin-updates` +** `mvn versions:display-property-updates` + +== Shared build resources + +There are several projects in the build tooling. The following special procedure is used to release updates to these. + +The parent-pom has the `uima-build-resources`'s version number encoded as the property + +``` +XXXXXX +``` + +This value will normally be set to the last released version number of the `uima-build-resource` artifact. + +If that artifact is changing, during development, this will be set to the `XX-SNAPSHOT` value corresponding to the development version. When releasing, first do a release (to the Nexus Staging repository, as usual) of the `uima-build-resources` artifact, which will create a version without the `-SNAPSHOT`. Then change the `` value to correspond to the non-SNAPSHOT version number of this, before proceeding to release the parent-pom artifact. + + + + + + + diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc new file mode 100644 index 0000000000..45150784d0 --- /dev/null +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + += Apache UIMA™ +:Author: Apache UIMA™ Development Community +:toc-title: UIMA Maintainer's Guide + +The document is a manual for maintainers of Apache UIMA, specifically focusing on aspects such as +preparing releases etc. Although this is part of the documentation of the UIMA Java SDK, many +aspects also apply to other Apache UIMA sub-projects. + +include::common_book_info.adoc[leveloffset=+1] + +include::uv3.release.adoc[leveloffset=+1] diff --git a/uima-doc-v3-users-guide/pom.xml b/uima-doc-v3-users-guide/pom.xml index 8e98f04b86..fc77928cd4 100644 --- a/uima-doc-v3-users-guide/pom.xml +++ b/uima-doc-v3-users-guide/pom.xml @@ -31,7 +31,7 @@ uima-doc-v3-users-guide pom - Apache UIMA SDK Documentation - Version 3 user's guide + Apache UIMA SDK Documentation - Version 3 User's Guide ${uimaWebsiteUrl} diff --git a/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc b/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc index cc6735e469..b6f0cd89df 100644 --- a/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc +++ b/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc @@ -19,7 +19,7 @@ :Author: Apache UIMA™ Development Community :toc-title: UIMA 3 User's Guide -The document is a manual for users of Apache UIMA, specifically focussing on the new +The document is a manual for users of Apache UIMA, specifically focusing on the new features introduced in version 3. include::common_book_info.adoc[leveloffset=+1] From f415f1fbc0730cede37093cc80834fdee88b51e7 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 27 Apr 2022 17:08:14 +0200 Subject: [PATCH 02/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide - Add maintainer one-time-setup page - Try having the CSS file separate instead of inlining it --- uima-doc-v3-maintainers-guide/pom.xml | 2 + .../src/docs/asciidoc/uv3.one-time-setup.adoc | 49 ++++++++++++++++ .../src/docs/asciidoc/uv3.release.adoc | 56 +++++++++++-------- .../asciidoc/version_3_maintainers_guide.adoc | 2 + 4 files changed, 86 insertions(+), 23 deletions(-) create mode 100644 uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc diff --git a/uima-doc-v3-maintainers-guide/pom.xml b/uima-doc-v3-maintainers-guide/pom.xml index 33adbe7f6a..e8109f3de1 100644 --- a/uima-doc-v3-maintainers-guide/pom.xml +++ b/uima-doc-v3-maintainers-guide/pom.xml @@ -88,6 +88,8 @@ https://uima.apache.org font true + false + true asciidoctor-pdf diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc new file mode 100644 index 0000000000..e4f8b7a809 --- /dev/null +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + += Maintainer Setup + +== Java + +Most Apache UIMA code is written in Java. To build it, you need a recent Java Development Kit (JDK) which can be obtained from the link:https://adoptium.net[Eclipse Adoptium] project - but there are also plenty of other JDK vendors offering free JDKs (or even ones with commercial support). + +The minimum Java version required for Apache UIMA is: **1.8** + +It is recommended to install the latest long term support (LTS) Java version and use it for development. When performing a release, a minimum-version JDK should be used to ensure compatibility for downstream users. + +== Version control: Git and Subversion + +Apache UIMA projects use Subversion as well as Git. Thus, you should install a Subversion client as well as a Git client - best the latest available version. +If you are using an IDE, you should also install a suitable Subversion and Git plugin for the IDE. Most IDEs come with Git plugins already pre-installed. If you are lucky, it might be enough for you. If you need to work with one of the older Subversion repositories of the project, having the Subversion plugin is handy as well. + +NOTE: Configure your SVN client to set the eol-style to native, for newly created files; see https://apache.org/dev/svn-eol-style.txt for instructions on how to do this. + +== IDE: Eclipse or another one + +Eclipse is usually the IDE of choice for UIMA developers because UIMA provides several Eclipse plugins to facilitate editing UIMA XML descriptor files and the example projects are also currently provided as Eclipse projects. + +NOTE: You can also use another IDE like IntelliJ, Netbeans or even VSCode because the builds themselves is largely driven by Maven - **but for building the Eclipse update sites as part of the release process, also an Eclipse installation is required.** + +== Build tool: Maven + +Most Apache UIMA sub-projects are built using Apache Maven version 3 or higher. Maven offers a largely declarative and convention-driven build process and in particular automatically downloads required third-party libraries from the internet, in particular from the link:https://search.maven.org[Maven Central] repository. + +You can download the latest Maven version from https://maven.apache.org/download.html or install it using your favourite package manager. Most Java IDEs already come with Maven support pre-installed. If your IDE does not offer Maven support out-of-the-box, you may want to install a suitable plugin. + +* Download the latest Apache Maven from . +* Set up your `PATH`` to use this version. +* (Optional, but is needed for some JVM/platforms, to give the JVM enough room to build things). Set the environment variable `MAVEN_OPTS` to `-Xmx800m -XX:MaxPermSize=256m` diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index a025adfad0..4c20385a27 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -= UIMA Release Process += Release Process The Apache UIMA project mainly releases: @@ -34,12 +34,10 @@ As part of the planning, new issues are created and typically one somebody assig There is no fixed release schedule. Anybody may ask for the preparation of a new release. A committer then has to step up to act as the release manager and to perform the release process. -== Maintainer one-time setup - -FIXME: link:https://uima.apache.org/one-time-release-setup.html[old website] - == Performing the release +=== Preparations + * {empty} + .Create release issue and release preparation branch @@ -103,6 +101,18 @@ Running the mvn release... command will cause this report to be generated or upd ==== Update the parent-pom settings for API change reports setting `api_check_old_version` to the correct previous version to use. ==== +* {empty} ++ +.Check that the Eclipse `.classpath` files which are checked in as part of the examples have the proper version numbers for their JARs +[%collapsible] +==== +If the release includes Eclipse projects as examples and the release includes also new or updated dependencies, the Eclipse `.classpath` files in the example projects may need to be updated to include the new libraries. + +NOTE: There may be a generation process involved. E.g. in the UIMA Java SDK, the template for the `.classpath` files can be found in `uimaj-examples/src/main/eclipseProject/classpath`. +==== + +=== Building + * {empty} + .Clean local m2 repository @@ -118,6 +128,15 @@ For many multi-module projects, this will fail because it purges things that oth ==== * {empty} + +.Commit all changes and check out in a new clean build location +[%collapsible] +==== +Make sure all changes are checked into source control. Then checkout (not export) from source control the project(s) you'll be building, into a new *build* location, and do all the building from there. + +If you instead choose to build from your *working* source control checkout, insure it's up-to-date with all changes that others may have checked into the release branch. +==== +* {empty} ++ .Run a trial build locally with `-Papache-release` [%collapsible] ==== @@ -139,24 +158,6 @@ There is a saved "filter" you can adjust for this that will display all fixed Ji ==== * {empty} + -.Check that the Eclipse `.classpath` files which are checked in as part of the examples have the proper version numbers for their JARs -[%collapsible] -==== -If the release includes Eclipse projects as examples and the release includes also new or updated dependencies, the Eclipse `.classpath` files in the example projects may need to be updated to include the new libraries. - -NOTE: There may be a generation process involved. E.g. in the UIMA Java SDK, the template for the `.classpath` files can be found in `uimaj-examples/src/main/eclipseProject/classpath`. -==== -* {empty} -+ -.Commit all changes and check out in a new clean build location -[%collapsible] -==== -Make sure all changes are checked into source control. Then checkout (not export) from source control the project(s) you'll be building, into a new *build* location, and do all the building from there. - -If you instead choose to build from your *working* source control checkout, insure it's up-to-date with all changes that others may have checked into the release branch. -==== -* {empty} -+ .Do the release build (`mvn -DautoVersionSubmodules=true release:prepare release:perform`) [%collapsible] ==== @@ -184,6 +185,9 @@ Exception to this: `-SNAPSHOT` suffixes are not updated for references within pl Note that any JARs, Zips, Tars, tar.gz artifacts must be signed by the Release Manager. When `-Papache-release` is active, the GPG Maven Plugin runs and signs the artifacts with the user's default GPG key. If you have multiple keys on your system, make sure to switch default to the right key before the release. ==== + +=== Staging + * {empty} + .Close the staging repository at http://repository.apache.org/ @@ -264,6 +268,9 @@ FIXME: Eclipse update site process needs updating... For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. ==== + +=== Voting + * {empty} + .Call for a vote on the developer mailing list using the email template below @@ -340,6 +347,9 @@ Thanks to all who voted! -- __Release manager name__ ---- ==== + +=== Publishing + * {empty} + .Copy the release artifacts from the staging spot to the dist spot in SVN diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc index 45150784d0..838dd99075 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc @@ -25,4 +25,6 @@ aspects also apply to other Apache UIMA sub-projects. include::common_book_info.adoc[leveloffset=+1] +include::uv3.one-time-setup.adoc[leveloffset=+1] + include::uv3.release.adoc[leveloffset=+1] From d238dfd56342e248bc3bd9ab447dc7ab018a107d Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 27 Apr 2022 18:59:25 +0200 Subject: [PATCH 03/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide - Formatting --- .../src/docs/asciidoc/uv3.release.adoc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 4c20385a27..040be44b7f 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -82,15 +82,19 @@ The Maven release plugin will complain if there are still any `SNAPSHOT` depende ==== Edit the POM of the top level thing being released, to add the property: +---- 2.10.2SDK +---- -replacing the 2.10.2SDK with the actual Jira version name for the Jira release being done. This value is used during release processing to automatically generate a report of the list of Jira issues that are included in this release. Change "2.10.2SDK"" to be the actual jira version name, which you can get from the Jira url by going to https://issues.apache.org/jira/browse/UIMA and selecting "Releases" and then going to the particular version and copying its name. +replacing the `2.10.2SDK` with the actual Jira version name for the Jira release being done. This value is used during release processing to automatically generate a report of the list of Jira issues that are included in this release. Change `2.10.2SDK` to be the actual jira version name, which you can get from the Jira URL by going to https://issues.apache.org/jira/browse/UIMA and selecting **Releases** and then going to the particular version and copying its name. -You can also generate this report manually (for instance, if you want to have a look at what it will produce) by going to top level project being released (e.g., uimaj-distr) and issuing the maven command: +You can also generate this report manually (for instance, if you want to have a look at what it will produce) by going to top level project being released (e.g., `uima-uimaj`) and issuing the maven command: +---- mvn changes:jira-report -N +---- -Each time this plugin is run, it creates an updated report in the top level of this project. This report doesn't need to be checked into source control. It will be regenerated and copied into the distribution archives (source and binary) during a release. The RELEASE_NOTES.html files have been updated to refer to this generated report. +Each time this plugin is run, it creates an updated report in the top level of this project. This report doesn't need to be checked into source control. It will be regenerated and copied into the distribution archives (source and binary) during a release. The `RELEASE_NOTES.html` files have been updated to refer to this generated report. Running the mvn release... command will cause this report to be generated or updated, every time the command is run. So it is important that the POM is updated to include the internal Jira version number, so the right report is generated. ==== From 5535ecf143b7a205cae742e3366021cf9b1ac77c Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 29 Apr 2022 13:11:03 +0200 Subject: [PATCH 04/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide - Disable publishing HTML again because we do it via a separate Jenkins job now --- Jenkinsfile | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1b285b3590..7d2ed34788 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,20 +15,10 @@ // specific language governing permissions and limitations // under the License. -@Library('uima-build-jenkins-shared-library@feature/UIMA-6437-Allow-publishing-HTML-documentation-from-Jenkinsfile') _ +@Library('uima-build-jenkins-shared-library') _ defaultPipeline { // The Eclipse libraries that our plugins depend unfortunately on required Java 11 jdk = 'jdk_11_latest' extraMavenArguments = '-Pjacoco,pmd,run-rat-report' - documentation = [[ - allowMissing: false, - alwaysLinkToLastBuild: true, - keepAll: false, - reportDir: 'uima-doc-v3-maintainers-guide/target/site/d', - includes: '**/*', - reportFiles: 'version_3_maintainers_guide.html', - reportName: 'Maintainers Guide', - reportTitles: 'Maintainers Guide' - ]] } From 681f7525e00f19fb74d8d340066496a104b9a5dd Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 11 May 2022 11:15:43 +0200 Subject: [PATCH 05/94] [UIMA-6443] Fresh Eclipse update site for every release - Remove duplicate SCM declaration --- pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pom.xml b/pom.xml index d64d09b62b..6b02eacf5f 100644 --- a/pom.xml +++ b/pom.xml @@ -52,13 +52,6 @@ ${ibmNoticeText} - - scm:git:https://github.com/apache/uima-uimaj/ - scm:git:https://github.com/apache/uima-uimaj/ - https://github.com/apache/uima-uimaj/ - uimaj-3.2.0 - - From 47efebe7c13aff1e0bbfc7a8a5b1478c0defea56 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 11 May 2022 11:29:57 +0200 Subject: [PATCH 06/94] [UIMA-6443] Fresh Eclipse update site for every release - Update version to the version used on the main branch --- uimaj-eclipse-feature-runtime/pom.xml | 2 +- uimaj-eclipse-feature-tools/pom.xml | 16 ++++++++-------- uimaj-eclipse-maven-p2-site/pom.xml | 2 +- uimaj-eclipse-update-site/pom.xml | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/uimaj-eclipse-feature-runtime/pom.xml b/uimaj-eclipse-feature-runtime/pom.xml index 06c810d1a4..6dcbe72cb2 100644 --- a/uimaj-eclipse-feature-runtime/pom.xml +++ b/uimaj-eclipse-feature-runtime/pom.xml @@ -40,7 +40,7 @@ org.apache.uima uimaj-ep-runtime - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT \ No newline at end of file diff --git a/uimaj-eclipse-feature-tools/pom.xml b/uimaj-eclipse-feature-tools/pom.xml index 3f7c2c8200..9151f5708c 100644 --- a/uimaj-eclipse-feature-tools/pom.xml +++ b/uimaj-eclipse-feature-tools/pom.xml @@ -38,42 +38,42 @@ org.apache.uima org.apache.uima.runtime - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-cas-editor - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-cas-editor-ide - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-configurator - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-debug - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-jcasgen - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-pear-packager - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima uimaj-ep-launcher - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT \ No newline at end of file diff --git a/uimaj-eclipse-maven-p2-site/pom.xml b/uimaj-eclipse-maven-p2-site/pom.xml index 963cd098fd..cd600e6edb 100644 --- a/uimaj-eclipse-maven-p2-site/pom.xml +++ b/uimaj-eclipse-maven-p2-site/pom.xml @@ -25,7 +25,7 @@ org.apache.uima uimaj-parent - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT ../uimaj-parent/pom.xml diff --git a/uimaj-eclipse-update-site/pom.xml b/uimaj-eclipse-update-site/pom.xml index 854d70a815..46a0eabb9e 100644 --- a/uimaj-eclipse-update-site/pom.xml +++ b/uimaj-eclipse-update-site/pom.xml @@ -45,12 +45,12 @@ org.apache.uima org.apache.uima.runtime - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.uima org.apache.uima.tools - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT From 8b64502a8fba6584474459401dc1b3647c409971 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 11 May 2022 13:51:21 +0200 Subject: [PATCH 07/94] [UIMA-6443] Fresh Eclipse update site for every release - Update version in Eclipse metadata --- uimaj-eclipse-feature-runtime/feature.xml | 2 +- uimaj-eclipse-feature-tools/feature.xml | 4 ++-- uimaj-eclipse-update-site/category.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/uimaj-eclipse-feature-runtime/feature.xml b/uimaj-eclipse-feature-runtime/feature.xml index f0b1c15dae..a270daf183 100644 --- a/uimaj-eclipse-feature-runtime/feature.xml +++ b/uimaj-eclipse-feature-runtime/feature.xml @@ -20,7 +20,7 @@ diff --git a/uimaj-eclipse-feature-tools/feature.xml b/uimaj-eclipse-feature-tools/feature.xml index 2ea01a5850..c52a24d3ed 100644 --- a/uimaj-eclipse-feature-tools/feature.xml +++ b/uimaj-eclipse-feature-tools/feature.xml @@ -20,7 +20,7 @@ @@ -153,7 +153,7 @@ Apache UIMA is a trademark of the Apache Software Foundation in the United State diff --git a/uimaj-eclipse-update-site/category.xml b/uimaj-eclipse-update-site/category.xml index 4bf11cccf0..55ed5a5960 100644 --- a/uimaj-eclipse-update-site/category.xml +++ b/uimaj-eclipse-update-site/category.xml @@ -20,10 +20,10 @@ *************************************************************** --> - + - + From 46464f4a46ae2a4bd83915c1affb33cf4088b544 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 13 May 2022 10:40:48 +0200 Subject: [PATCH 08/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide - Add section on project structure --- .../docs/asciidoc/uv3.project_structure.adoc | 51 +++++++++++++++++++ .../asciidoc/version_3_maintainers_guide.adoc | 2 + 2 files changed, 53 insertions(+) create mode 100644 uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc new file mode 100644 index 0000000000..a56b42bf43 --- /dev/null +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + += Project structure + +To keep the folder structure lean so it doesn't dominate the view when looking at a repository in GitHub, the project should conform to the following structure. This should allow the contents of the `README.md` file to still be visible without too much scrolling +when visiting the project's repository in a web browser. + +`README.md` :: + Version-independent description of the project + +`RELEASE_NOTES.md` :: + Specific information about the last release. + +`NOTICE.txt` :: + Copyright information + +`LICENSE.txt` :: + License information + +`Jenkinsfile` :: + Configuration file for building the project on the ASF Jenkins. + +`pom.xml` :: + Entry point for Maven-based (Java) projects. + +`.asf.yaml` :: + Configuration file for the ASF GitHub integration. + +`.gitignore` / `.gitattributes`` :: + Git configuration files as required + +`.github` :: + GitHub configuration and tempalte files + +`src/` :: + Folder containing the actual source code. \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc index 838dd99075..23126b6300 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc @@ -27,4 +27,6 @@ include::common_book_info.adoc[leveloffset=+1] include::uv3.one-time-setup.adoc[leveloffset=+1] +include::uv3.project_structure.adoc[leveloffset=+1] + include::uv3.release.adoc[leveloffset=+1] From 85301afa8f0c7656a94276a8d0771f74574e654b Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 13 May 2022 10:43:16 +0200 Subject: [PATCH 09/94] [UIMA-6438] Add asf.yaml files to UIMA repos - Align with files in other repos - Add explicit configuration for notifications, dependabot, features, etc. etc. - Add branch protection (unfortunately, wildcards are currently not supported in asf.yaml...) --- .asf.yaml | 63 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index 6e2e72b049..db9bdaf89c 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -1,19 +1,54 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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 # -# http://www.apache.org/licenses/LICENSE-2.0 +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 # -# 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. +# http://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. +# + github: description: "UIMA Java SDK, version 3 (in main), 2 (in main-v2)" homepage: https://uima.apache.org + dependabot_alerts: true + dependabot_updates: false + notifications: + commits: commits@uima.apache.org + issues: dev@uima.apache.org + pullrequests: dev@uima.apache.org + jobs: dev@uima.apache.org + jira_options: link label + labels: + - apache + - uima + - text-analysis + features: + wiki: false + issues: false + projects: false + enabled_merge_buttons: + squash: true + merge: true + rebase: false + del_branch_on_merge: true + protected_branches: + main: + required_status_checks: + strict: true + contexts: + - continuous-integration/jenkins/pr-merge + main-v2: + required_status_checks: + strict: true + contexts: + - continuous-integration/jenkins/pr-merge + + \ No newline at end of file From 961a130f5a3125a159c92aabceae43a102b140e5 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 13 May 2022 18:47:54 +0200 Subject: [PATCH 10/94] [UIMA-6454] Update dependencies (UIMA Java SDK 3.3.1) - Apache UIMA Parent POM 14 -> 15-SNAPSHOT --- uimaj-parent/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index 83d4035730..7a80ab2e66 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -32,7 +32,7 @@ org.apache.uima parent-pom - 14 + 15-SNAPSHOT uimaj-parent @@ -74,6 +74,7 @@ - The Eclipse Plugin modules use version ranges for their dependencies. These could resolve to - SNAPSHOT versions if we have a SNAPSHOT repo declaration here. Thus, this repo should only - be enabled when really needed. + --> apache.snapshots Apache Snapshot Repository @@ -85,7 +86,6 @@ true - --> ${eclipseP2RepoId} From ec3ba0017cde91ffd9a2c1c1352e581e490eab28 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 19 May 2022 16:21:05 +0200 Subject: [PATCH 11/94] [UIMA-6459] Upgrade dependencies (UIMAJ 3.4.0) - UIMA Parent POM 14 -> 15-SNAPSHOT - Remove auto-release-staging configuration and tycho configurations which are already in parent POM 15 --- marker-file-enabling-auto-staging | 0 marker-file-identifying-parent-pom | 0 pom.xml | 115 ++++------------------------- uimaj-parent/pom.xml | 114 +--------------------------- 4 files changed, 16 insertions(+), 213 deletions(-) create mode 100644 marker-file-enabling-auto-staging create mode 100644 marker-file-identifying-parent-pom diff --git a/marker-file-enabling-auto-staging b/marker-file-enabling-auto-staging new file mode 100644 index 0000000000..e69de29bb2 diff --git a/marker-file-identifying-parent-pom b/marker-file-identifying-parent-pom new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pom.xml b/pom.xml index 6b02eacf5f..5130c9b3ec 100644 --- a/pom.xml +++ b/pom.xml @@ -138,22 +138,22 @@ org.apache.uima uimaj-json ${project.version} - + org.apache.uima uimaj-v3migration-jcas ${project.version} - + org.bitbucket.mstrobel procyon-core 0.5.32 - + org.bitbucket.mstrobel procyon-compilertools 0.5.32 - + com.github.javaparser javaparser-core @@ -172,18 +172,17 @@ org.apache.logging.log4j log4j-slf4j-impl ${log4j-version} - + org.apache.logging.log4j log4j-core ${log4j-version} - + org.apache.logging.log4j log4j-api ${log4j-version} - - + @@ -272,6 +271,7 @@ + marker-file-rc-auto-staging-module NOTICE.md src/main/bin_distr_license_notices/NOTICE.md @@ -333,50 +333,8 @@ apache-release - - - scm:svn:https://dist.apache.org/repos/dist/dev/uima/ - ${project.build.directory}/staging - ${project.artifactId}-${project.version}-RC-${staging-timestamp}-${candidate-id} - - - - - - maven-changes-plugin - false - - - default-cli - - ${jiraVersion} - - - - - - org.codehaus.mojo - buildnumber-maven-plugin - false - - - generate-candidate-id - initialize - - create - - - candidate-id - staging-timestamp - 7 - yyyyMMddHHmm - Z - - - - org.apache.maven.plugins maven-antrun-plugin @@ -392,17 +350,17 @@ - - - - - - + + + + + + - + @@ -410,49 +368,6 @@ - - org.apache.maven.plugins - maven-scm-plugin - false - - developerConnection - ${staging-scm-root} - - - - checkout-staging - initialize - - checkout - - - ${staging-local-root} - - - - add-staging-files - deploy - - add - - - ${staging-local-root} - ${staging-folder}/**/* - - - - commit-staging-files - deploy - - checkin - - - ${staging-local-root} - Staging release artifacts for ${project.artifactId}-${project.version}-RC-${staging-timestamp}-${candidate-id} - - - - diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index f2f759d00f..6d70c1978d 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -32,7 +32,7 @@ org.apache.uima parent-pom - 15-SNAPSHOT + 15-meep uimaj-parent @@ -119,20 +119,9 @@ artifactory.openntf.org https://artifactory.openntf.org/openntf - - - tycho-snapshots - https://repo.eclipse.org/content/repositories/tycho-snapshots/ - - false - - - - 2.7.3-SNAPSHOT - - **/.tycho-consumer-pom.xml **/run_configuration/*.launch @@ -298,83 +286,10 @@ - - - org.apache.maven.plugins - maven-release-plugin - - - - org.eclipse.tycho:tycho-versions-plugin:${tycho-version}:update-eclipse-metadata - org.apache.maven.plugins:maven-scm-plugin:1.9.5:add - - - org.eclipse.tycho:tycho-versions-plugin:${tycho-version}:update-eclipse-metadata - org.apache.maven.plugins:maven-scm-plugin:1.9.5:add - - - - - org.apache.maven.plugins - maven-scm-plugin - - - default-cli - - add - checkin - - - - uimaj-eclipse-*/META-INF/MANIFEST.MF, - uimaj-eclipse-*/feature.xml, - uimaj-eclipse-*/*.product, - uimaj-eclipse-*/category.xml - - **/target/** - Changing the Eclipse files versions - - - - - - apache-release - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - enforce-java - - enforce - - - - - - [1.8,1.9) - - - - - - - - - - jacoco @@ -440,33 +355,6 @@ - - - tycho-module - - - marker-file-identifying-tycho-module - - - - - - org.eclipse.tycho - tycho-maven-plugin - ${tycho-version} - true - - - org.eclipse.tycho - target-platform-configuration - ${tycho-version} - - consider - - - - - From e360ce2d0a80b8953d11da27993668527908419e Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 12:33:07 +0200 Subject: [PATCH 12/94] [UIMA-6459] Upgrade dependencies (UIMAJ 3.4.0) - Fix parent pom version - Fix order of toc entries in RELEASE_NOTES.md --- RELEASE_NOTES.md | 2 +- uimaj-parent/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7a168e0f15..5d8004091d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -25,9 +25,9 @@ [What is UIMA?](#what.is.uima) [Major Changes in this Release](#major.changes) +[List of JIRA Issues Fixed in this Release](#list.issues) [How to Get Involved](#get.involved) [How to Report Issues](#report.issues) -[List of JIRA Issues Fixed in this Release](#list.issues) ## What is UIMA? diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index 6d70c1978d..5fd2e4da88 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -32,7 +32,7 @@ org.apache.uima parent-pom - 15-meep + 15-SNAPSHOT uimaj-parent From d11d45d18fd5446a40f114d6b8707ce33d0d0f40 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 14:25:49 +0200 Subject: [PATCH 13/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Add documentation for auto-staging and generating Jira change reports * Add information how to avoid having to update the `jiraVersion` property of every release and deprecate the step in the checklist --- .../src/docs/asciidoc/uv3.maven.adoc | 65 +++++++++++++++++++ .../docs/asciidoc/uv3.project_structure.adoc | 9 +-- .../src/docs/asciidoc/uv3.release.adoc | 15 ++++- .../asciidoc/version_3_maintainers_guide.adoc | 2 + 4 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc new file mode 100644 index 0000000000..de2d7ec2da --- /dev/null +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc @@ -0,0 +1,65 @@ += Maven Build + +This section describes various functionalities provided by the UIMA Parent POM and how to use them in downstream projects. + +== Issues fixed report + +In order for your project to generate an **issues fixed** report from the ASF Jira, add +an empty file called `marker-file-identifying-parent-pom` to the root of your Maven project. +This activates the `mavenJirareport` profile from the parent POM. + +Additionally, set the property `jiraVersion` in the `pom.xml` at your project's root to + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}SUFFIX + +The properties are provided by the `build-helper-maven-plugin` in the UIMA Parent POM. You just need to add the `SUFFIX` for your project depending on how it is called in Jira, e.g. `SDK` for the Apache Java SDK or `uimaFIT` for uimaFIT. + + +== Auto-staging of release candidates + +Once the release build is complete, the artifacts need to be uploaded to the ASF Subversion repository for voting. To avoid having to perform this step manually, the Maven build includes an auto-staging mechanism. To use this mechansim, place an empty file called `marker-file-enabling-auto-staging`. This file activates the profile `apache-release-rc-auto-staging`. + +Additionally, you have to add an execution to your project's root Maven POM that copies the release artifacts to a local staging folder. At the start of the build, the auto-staging profile will check out the ASF Subversion repository RC staging spot to that local staging folder. Then your execution kicks in to copy the RC artifacts into the local folder. Finally, the auto-staging profile will add and commit the artifacts to Subversion. + +Below is an example of how to copy the release artifacts to the local staging spot. The variables `${staging-local-root}` and `${staging-folder}` are provided by the UIMA Parent POM. + + + + apache-release + + + + org.apache.maven.plugins + maven-antrun-plugin + false + + + install + + run + + + + + + + + + + + + + + + + + + + + + +To test the auto-staging mechanism, you can set up a local Subversion repository and then run a build that skips the Maven Deploy Plugin and which is configured to use your local Subversion repo for auto-staging: + +* Initialize a local svn repo: `svnadmin create /my/local/testrepo` +* Do a test build: `mvn -Papache-release -DskipTests -Dmaven.deploy.skip -Dstaging-scm-root='scm:svn:file:///my/local/testrepo/' clean deploy` +* Check if the commit made it in: `svn log file:///my/local/testrepo/` \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc index a56b42bf43..8a233d5093 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.project_structure.adoc @@ -17,8 +17,9 @@ = Project structure -To keep the folder structure lean so it doesn't dominate the view when looking at a repository in GitHub, the project should conform to the following structure. This should allow the contents of the `README.md` file to still be visible without too much scrolling -when visiting the project's repository in a web browser. +// REC: The following may not be necessary if we simply add `#readme` to all links to the repo e.g. in the documentation and on the website +// To keep the folder structure lean so it doesn't dominate the view when looking at a repository in GitHub, the project should conform to the following structure. This should allow the contents of the `README.md` file to still be visible without too much scrolling when visiting the project's repository in a web browser. + `README.md` :: Version-independent description of the project @@ -47,5 +48,5 @@ when visiting the project's repository in a web browser. `.github` :: GitHub configuration and tempalte files -`src/` :: - Folder containing the actual source code. \ No newline at end of file +// `src/` :: +// Folder containing the actual source code. \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 040be44b7f..24b04154b7 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -47,10 +47,10 @@ Our development branches (i.e. `main` and `maintenance/*`) should be protected, ==== * {empty} + -.Update `README` file +.Update `README.md` file [%collapsible] ==== -Make sure that any README files have been updated with the latest release information and release numbers. +If `README.md` file contains version references, update them. E.g. if you have a Maven dependency snippet in there. Optimally, the `README.md` file should not have any contents that need to change from version to version. ==== * {empty} + @@ -77,9 +77,18 @@ The Maven release plugin will complain if there are still any `SNAPSHOT` depende ==== * {empty} + -.Update Jira version in POM for fixed-issues report +.Update Jira version in POM for fixed-issues report **(deprecated)** [%collapsible] ==== +**Deprecated** + +Set the property to based on version variables to avoid having to update it every time. + + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}SUFFIX + + +---- + Edit the POM of the top level thing being released, to add the property: ---- diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc index 23126b6300..80188c1500 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/version_3_maintainers_guide.adoc @@ -29,4 +29,6 @@ include::uv3.one-time-setup.adoc[leveloffset=+1] include::uv3.project_structure.adoc[leveloffset=+1] +include::uv3.maven.adoc[leveloffset=+1] + include::uv3.release.adoc[leveloffset=+1] From e8e979e7d60e91dbe15f4471f0e4dd53dcc21cd0 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 14:29:08 +0200 Subject: [PATCH 14/94] [UIMA-6459] Upgrade dependencies (UIMAJ 3.4.0) - Use variables-based jiraVersion property to avoid having to update it on every release --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5130c9b3ec..3f65aae5c3 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ - 3.3.0SDK + ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}SDK src/main/assembly/bin-without-jackson.xml ${ibmNoticeText} From 4173364212d63ca0c2087d2fd3c5bcb62f7d1785 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 15:08:37 +0200 Subject: [PATCH 15/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Deprecate outdated release steps e.g. related to the old way of doing Eclipse update sites --- .../src/docs/asciidoc/uv3.release.adoc | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 24b04154b7..de865c9efd 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -109,7 +109,7 @@ Running the mvn release... command will cause this report to be generated or upd ==== * {empty} + -.Update API comparison version in POM +.Update API reference version in POM [%collapsible] ==== Update the parent-pom settings for API change reports setting `api_check_old_version` to the correct previous version to use. @@ -217,10 +217,12 @@ If you forget something and close the staging repository too soon, just continue ==== * {empty} + -.Upload artifacts from `target/checkout/target` to a subdirectory of the release staging spot +.Check that files have been auto-staged (or stage manually) [%collapsible] ==== -We have a spot at https://dist.apache.org/repos/dist/dev/uima/ for all the artifacts to be released via the Apache mirror system. This is where you put the release candidates. +We have a spot at https://dist.apache.org/repos/dist/dev/uima/ for staging all the release candidate artifacts to be later fully released via the Apache mirror system. + +The UIMA Parent POM offsets an auto-staging mechanism for release candidate artifacts that you should use. If it is not usable for you, then you have to stage the artifacts manually. Be sure to copy artifacts from the build-from tag spot, which should have a path like: `...[top level project]/target/checkout/target`. Note this is **NOT** from `[top level project]/target`. Doing this will guarantee that you're posting the artifacts built from the tag (which could be different from the `release:prepare` build in /target if someone snuck in a svn commit at the right moment.) @@ -235,28 +237,28 @@ Do not add files like POMs which have line-endings, if they have signatures; the ==== * {empty} + -.Update the version in the `uimaj-eclipse-update-site` +.Update the version in the `uimaj-eclipse-update-site` **(deprecated)** [%collapsible] ==== -FIXME: Eclipse update site process needs updating... +**Deprecated:** Use Tycho instead to build update sites along with every regular build. For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. ==== * {empty} + -.Set `dropPrevVersions` to `true` in the `uimaj-eclipse-update-site` POM +.Set `dropPrevVersions` to `true` in the `uimaj-eclipse-update-site` POM **(deprecated)** [%collapsible] ==== -FIXME: Eclipse update site process needs updating... +**Deprecated:** Use Tycho instead to build update sites along with every regular build. For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. ==== * {empty} + -.Build the `uimaj-eclipse-update-site` module with {{-Papache-release}} +.Build the `uimaj-eclipse-update-site` module with {{-Papache-release}} **(deprecated)** [%collapsible] ==== -FIXME: needs update! +**Deprecated:** Use Tycho instead to build update sites along with every regular build. For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. @@ -274,9 +276,11 @@ If you changed the composite site, bump up the version of .../build/uima-eclipse ==== * {empty} + -.Upload the update site to a subdirectory of the release staging spot and *commit* (*Caution:* the update site contains a `.svn` folder that needs to be removed!) +.Upload the update site to a subdirectory of the release staging spot and *commit* (*Caution:* the update site contains a `.svn` folder that needs to be removed!) **(deprecated)** [%collapsible] ==== +**Deprecated:** Use auto-staging instead. + FIXME: Eclipse update site process needs updating... For a general background on how we build P2 sites, including Composite update sites, see link:https://uima.apache.org/eclipse-update-site.html[eclipse-update-site] page. From 1bc8b6b8c0154259313f2eb6f633a6be44cfe73a Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 15:32:28 +0200 Subject: [PATCH 16/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Provide tips on signature and hash validation * Provide tips on additional release quality checking --- .../src/docs/asciidoc/uv3.release.adoc | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index de865c9efd..b8aca89e64 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -334,14 +334,83 @@ Thanks. ==== * {empty} + -.VOTE (wait at least for 72 hours, at least 3 +1 votes required for release) +.Mandatory release candidate signatures and hashes validation +[%collapsible] +==== +**Before casting +1 binding votes, individuals are REQUIRED to download all signed source code packages onto their own hardware, verify that they meet all requirements of ASF policy on releases as described below, validate all cryptographic signatures, compile as provided, and test the result on their own platform.** + +.Create a release candidate validation folder +---- +% mkdir rc-validation +% cd rc-validation +---- + +First we fetch the staged artifacts from the ASF staging spot as well as from the ASF Maven staging repository. If there is an Eclipse update site, it should be included under the ASF staging spot. + +.Fetch artifacts +---- +% svn co https://dist.apache.org/repos/dist/dev/uima/RELEASE-CANDIDATE-ID +% lftp -e "mirror org; exit" https://repository.apache.org/content/repositories/STAGING-REPO-ID +---- + +.Check GPG signatures +---- +% find org -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' ')' -type f -print0 | xargs -I '{}' -0 -n1 gpg --verify '{}'.asc '{}' +---- + +.Check SHA512 hashes +---- +% find . -name "*.sha512" -print0 | xargs -n1 -0 -I '{}' zsh -c 'cd `dirname {}`; sha512sum -c `basename {}`' +---- + +Checking SHA1/MD5 is a bit tedious because the hashsum files do not contain the filename and so the `sha1sum` and `md5sum` checking functionality does not work. We have to do set up a little script to help us. + +.Check SHA1/MD5 hashes +---- +% cat > checkHashes.sh +tmp="$(mktemp /tmp/tmp.XXXXXXXXXX)" +md5hash=`cat $1.md5` +sha1hash=`cat $1.sha1` +echo "$sha1hash $1" > "$tmp" +printf "SHA1 " +sha1sum -c "$tmp" +echo "$md5hash $1" > "$tmp" +printf "MD5 " +md5sum -c "$tmp" +rm "$tmp" + + +% chmod +x checkHashes.sh + +% find org -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' ')' -type f -print0 | xargs -I '{}' -0 -n1 ./checkHashes.sh '{}' + +% rm checkHashes.sh +---- + +For more information on the ASF release policy, please see the official link:https://www.apache.org/legal/release-policy.html[Release Policy] document. +==== +* {empty} ++ +.Additional release quality checking +[%collapsible] +==== +* Check the issues-fixed report +* Check the release notes +* Run a local build from the sources zip +* Install plugins into Eclipse +* Try out an example +* ... +==== +* {empty} ++ +.Vote [%collapsible] ==== See also https://www.apache.org/foundation/voting.html ==== * {empty} + -.Post vote results to the developer mailing list (sign mail using same GPG key that was used to sign release) +.Close vote and post vote results to the developer mailing list (wait at least for 72 hours, at least 3 +1 votes required for release, sign mail using same GPG key that was used to sign release) [%collapsible] ==== .Example vote results mail From 9df151bf0b0d2297d071b616c91c7638fe6729d7 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 15:44:26 +0200 Subject: [PATCH 17/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Additional explanations on signature and checksum checking --- .../src/docs/asciidoc/uv3.release.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index b8aca89e64..96db6723b2 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -353,17 +353,21 @@ First we fetch the staged artifacts from the ASF staging spot as well as from th % lftp -e "mirror org; exit" https://repository.apache.org/content/repositories/STAGING-REPO-ID ---- +All files (except hash files,detached signatures, or a few controle files like `maven-metadata.xml`) should have a detached signature. Check that this detached signature exists and validates against the file. + .Check GPG signatures ---- % find org -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' ')' -type f -print0 | xargs -I '{}' -0 -n1 gpg --verify '{}'.asc '{}' ---- +Check that all the SHA512 checksums are valid. (To do: also check that all files have the required SHA512 checksums) + .Check SHA512 hashes ---- % find . -name "*.sha512" -print0 | xargs -n1 -0 -I '{}' zsh -c 'cd `dirname {}`; sha512sum -c `basename {}`' ---- -Checking SHA1/MD5 is a bit tedious because the hashsum files do not contain the filename and so the `sha1sum` and `md5sum` checking functionality does not work. We have to do set up a little script to help us. +Checking SHA1/MD5 files generated by the Maven Repository is a bit tedious because the hashsum files do not contain the filename and so the `sha1sum` and `md5sum` checking functionality does not work. We have to do set up a little script to help us. .Check SHA1/MD5 hashes ---- From 54eeebd85b649883f25644dc1625fdc417097ecc Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 15:49:54 +0200 Subject: [PATCH 18/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Nicer links --- .../src/docs/asciidoc/uv3.release.adoc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 96db6723b2..796360ea36 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -220,7 +220,7 @@ If you forget something and close the staging repository too soon, just continue .Check that files have been auto-staged (or stage manually) [%collapsible] ==== -We have a spot at https://dist.apache.org/repos/dist/dev/uima/ for staging all the release candidate artifacts to be later fully released via the Apache mirror system. +We have a link:https://dist.apache.org/repos/dist/dev/uima/[staging spot] for all the release candidate artifacts to be later fully released via the Apache mirror system. The UIMA Parent POM offsets an auto-staging mechanism for release candidate artifacts that you should use. If it is not usable for you, then you have to stage the artifacts manually. @@ -391,7 +391,7 @@ rm "$tmp" % rm checkHashes.sh ---- -For more information on the ASF release policy, please see the official link:https://www.apache.org/legal/release-policy.html[Release Policy] document. +For more information on the ASF release policy, please see the link:https://www.apache.org/legal/release-policy.html[Apache Release Policy] document. ==== * {empty} + @@ -410,7 +410,9 @@ For more information on the ASF release policy, please see the official link:htt .Vote [%collapsible] ==== -See also https://www.apache.org/foundation/voting.html +Send an email to the developer mailing list indicating your vote. + +For more information, please refer to the link:https://www.apache.org/foundation/voting.html[Apache Voting Process]. ==== * {empty} + From 5bedbc3798720a0982c8ee8fc74835c4052d58ec Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 16:55:10 +0200 Subject: [PATCH 19/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Update command for signature validation * Remove stage-release-artifacts.sh which has been superseded by the auto-staging mechanism --- stage-relesase-artifacts.sh | 49 ------------------- .../src/docs/asciidoc/uv3.release.adoc | 4 +- 2 files changed, 2 insertions(+), 51 deletions(-) delete mode 100755 stage-relesase-artifacts.sh diff --git a/stage-relesase-artifacts.sh b/stage-relesase-artifacts.sh deleted file mode 100755 index fb2da6ed60..0000000000 --- a/stage-relesase-artifacts.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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 -# -# http://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. -set -e - -if [ $# -eq 0 ] ; then - echo "Supply two arguments: version and release candidate number, e.g." - echo " stage-release-artifacts 3.3.0 1" - exit -fi - -STAGING_DIR="./target/release-staging" -VERSION="$1" -RC="$2" - -echo "Setting up local staging point at ${STAGING_DIR} (auto-deleted when script ends)" -trap 'rm -R "${STAGING_DIR}"' EXIT -mkdir "${STAGING_DIR}" - -echo "Copying release artifacts to local staging spot" -for artifact in `find . -path "./target/checkout/target/uimaj-${VERSION}*" | grep -v 'pom'` -do - cp ${artifact} ${STAGING_DIR} -done - -echo "Copying Eclipse update site to local staging spot" -cp -r uimaj-eclipse-update-site/target/eclipse-update-site-v3 "${STAGING_DIR}" - - -echo "Uploading local staging spot into ASF subversion" -pushd "${STAGING_DIR}" -svn import . -m "Staging release artifacts for ${VERSION}-RC${RC}" "https://dist.apache.org/repos/dist/dev/uima/uima-uimaj-${VERSION}-RC${RC}" -popd - -echo "Done" \ No newline at end of file diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 796360ea36..7896f0cda5 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -353,11 +353,11 @@ First we fetch the staged artifacts from the ASF staging spot as well as from th % lftp -e "mirror org; exit" https://repository.apache.org/content/repositories/STAGING-REPO-ID ---- -All files (except hash files,detached signatures, or a few controle files like `maven-metadata.xml`) should have a detached signature. Check that this detached signature exists and validates against the file. +All files (except hash files,detached signatures, or a few files like `maven-metadata.xml` or 'LICENSE' etc.) should have a detached signature. Check that this detached signature exists and validates against the file. .Check GPG signatures ---- -% find org -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' ')' -type f -print0 | xargs -I '{}' -0 -n1 gpg --verify '{}'.asc '{}' +% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 gpg --verify '{}'.asc '{}' ---- Check that all the SHA512 checksums are valid. (To do: also check that all files have the required SHA512 checksums) From 0f1f30811f6db2978035319055f53eff70891b27 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 16:57:47 +0200 Subject: [PATCH 20/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Update commands for checksum validation --- .../src/docs/asciidoc/uv3.release.adoc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 7896f0cda5..fe124d0d96 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -360,11 +360,12 @@ All files (except hash files,detached signatures, or a few files like `maven-met % find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 gpg --verify '{}'.asc '{}' ---- -Check that all the SHA512 checksums are valid. (To do: also check that all files have the required SHA512 checksums) +For the same set of files for which we checked the signatures, also check the SHA512 hashes are valid. .Check SHA512 hashes ---- -% find . -name "*.sha512" -print0 | xargs -n1 -0 -I '{}' zsh -c 'cd `dirname {}`; sha512sum -c `basename {}`' +% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 +-n1 zsh -c 'cd `dirname {}`; sha512sum -c `basename {}.sha512`' ---- Checking SHA1/MD5 files generated by the Maven Repository is a bit tedious because the hashsum files do not contain the filename and so the `sha1sum` and `md5sum` checking functionality does not work. We have to do set up a little script to help us. @@ -386,7 +387,7 @@ rm "$tmp" % chmod +x checkHashes.sh -% find org -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' ')' -type f -print0 | xargs -I '{}' -0 -n1 ./checkHashes.sh '{}' +% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 ./checkHashes.sh '{}' % rm checkHashes.sh ---- From 4c3de6e199acdfcdb7fda3c0b75623be22b39f1f Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 20 May 2022 18:27:17 +0200 Subject: [PATCH 21/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Add note that credentials are required for auto-staging --- .../src/docs/asciidoc/uv3.maven.adoc | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc index de2d7ec2da..05ff8aca30 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc @@ -24,40 +24,48 @@ Additionally, you have to add an execution to your project's root Maven POM that Below is an example of how to copy the release artifacts to the local staging spot. The variables `${staging-local-root}` and `${staging-folder}` are provided by the UIMA Parent POM. - + apache-release - + - org.apache.maven.plugins - maven-antrun-plugin - false - + org.apache.maven.plugins + maven-antrun-plugin + false + - install - + install + run - - + + - - + + - - - + + + - + - + - + - + - + +Also, it is necessary to add credentials to the `settings.xml` for the server to which the release candidate artifacts are staged. Normally, the server is `dist.apache.org`, so you need to add an entry such as e.g. + + + dist.apache.org + USERNAME + ENCRYPTED_PASSWORD + + To test the auto-staging mechanism, you can set up a local Subversion repository and then run a build that skips the Maven Deploy Plugin and which is configured to use your local Subversion repo for auto-staging: * Initialize a local svn repo: `svnadmin create /my/local/testrepo` From b8534b849c3d796ea26cc18ac10ac3af7b772edd Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 23 May 2022 08:59:06 +0200 Subject: [PATCH 22/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Improve commands for checking signatures and hashes * Use svn export instead of svn checkout to avoid having a `.svn` folder which is annoying for auto-checking signatures and hashes --- .../src/docs/asciidoc/uv3.release.adoc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index fe124d0d96..3a33c2043e 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -349,7 +349,7 @@ First we fetch the staged artifacts from the ASF staging spot as well as from th .Fetch artifacts ---- -% svn co https://dist.apache.org/repos/dist/dev/uima/RELEASE-CANDIDATE-ID +% svn export https://dist.apache.org/repos/dist/dev/uima/RELEASE-CANDIDATE-ID % lftp -e "mirror org; exit" https://repository.apache.org/content/repositories/STAGING-REPO-ID ---- @@ -357,15 +357,14 @@ All files (except hash files,detached signatures, or a few files like `maven-met .Check GPG signatures ---- -% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 gpg --verify '{}'.asc '{}' +% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 -S 2000 gpg --verify '{}'.asc '{}' ---- For the same set of files for which we checked the signatures, also check the SHA512 hashes are valid. .Check SHA512 hashes ---- -% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 --n1 zsh -c 'cd `dirname {}`; sha512sum -c `basename {}.sha512`' +% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 -S 2000 zsh -c 'cd `dirname {}`; sha512sum -c `basename {}.sha512`' ---- Checking SHA1/MD5 files generated by the Maven Repository is a bit tedious because the hashsum files do not contain the filename and so the `sha1sum` and `md5sum` checking functionality does not work. We have to do set up a little script to help us. @@ -387,7 +386,7 @@ rm "$tmp" % chmod +x checkHashes.sh -% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 ./checkHashes.sh '{}' +% find . -not '(' -name '*.md5' -or -name '*.sha*' -or -name '*.asc' -or -name 'maven-metadata.xml' -or -name 'DEPENDENCIES' -or -name 'LICENSE' -or -name 'NOTICE' ')' -type f -print0 | xargs -I '{}' -0 -n1 -S 2000 ./checkHashes.sh '{}' % rm checkHashes.sh ---- From 097a083150358e323dbed5553e055a4eef2ddc20 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 23 May 2022 09:18:44 +0200 Subject: [PATCH 23/94] [UIMA-6462] Avoid deploy broken checksum files for p2content.xml and artifacts.xml in feature modules - Prevent feature modules from being deployed - Add a marker file to the project root to trigger the Tycho release extensions --- marker-file-enabling-tycho-release | 0 uimaj-eclipse-feature-runtime/pom.xml | 5 +++++ uimaj-eclipse-feature-tools/pom.xml | 5 +++++ 3 files changed, 10 insertions(+) create mode 100644 marker-file-enabling-tycho-release diff --git a/marker-file-enabling-tycho-release b/marker-file-enabling-tycho-release new file mode 100644 index 0000000000..e69de29bb2 diff --git a/uimaj-eclipse-feature-runtime/pom.xml b/uimaj-eclipse-feature-runtime/pom.xml index 6dcbe72cb2..85a2a036ab 100644 --- a/uimaj-eclipse-feature-runtime/pom.xml +++ b/uimaj-eclipse-feature-runtime/pom.xml @@ -36,6 +36,11 @@ need UIMA framework code ${uimaWebsiteUrl} + + + true + + org.apache.uima diff --git a/uimaj-eclipse-feature-tools/pom.xml b/uimaj-eclipse-feature-tools/pom.xml index 9151f5708c..a77fc3f17c 100644 --- a/uimaj-eclipse-feature-tools/pom.xml +++ b/uimaj-eclipse-feature-tools/pom.xml @@ -34,6 +34,11 @@ UIMA Eclipse Plugin Feature for base uima tooling ${uimaWebsiteUrl} + + + true + + org.apache.uima From 782a40c9047cc7be9097c657f29e81cd0929919f Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 23 May 2022 10:24:54 +0200 Subject: [PATCH 24/94] [UIMA-6463] Use toolchains to ensure compatibility with Java 1.8 - Add toolchain plugin --- uimaj-parent/pom.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index 5fd2e4da88..ad5551e936 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -238,6 +238,24 @@ + + org.apache.maven.plugins + maven-toolchains-plugin + + + + toolchain + + + + + + + ${maven.compiler.target} + + + + com.github.siom79.japicmp From 4db01d8c18af7a439f8b421fdeceeac0fd142af6 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 23 May 2022 11:00:32 +0200 Subject: [PATCH 25/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Add section on Maven toolchains --- .../src/docs/asciidoc/uv3.one-time-setup.adoc | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc index e4f8b7a809..2fea228b6f 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.one-time-setup.adoc @@ -17,7 +17,7 @@ = Maintainer Setup -== Java +== Platform: Java Most Apache UIMA code is written in Java. To build it, you need a recent Java Development Kit (JDK) which can be obtained from the link:https://adoptium.net[Eclipse Adoptium] project - but there are also plenty of other JDK vendors offering free JDKs (or even ones with commercial support). @@ -47,3 +47,31 @@ You can download the latest Maven version from https://maven.apache.org/download * Download the latest Apache Maven from . * Set up your `PATH`` to use this version. * (Optional, but is needed for some JVM/platforms, to give the JVM enough room to build things). Set the environment variable `MAVEN_OPTS` to `-Xmx800m -XX:MaxPermSize=256m` + +=== Maven toolchains + +To ensure that an Apache UIMA build is actually compatible with the minimum system +requirements, it is important to build it against a minimum requirements environment. +However, it is possible that Maven or plugins we use no longer are able to run on the +same minimum system requirements that Apache UIMA aims to meet and thus for building, +you may need e.g. a never Java version. To ensure that we can still build against +the desired target environment, we use the link:https://maven.apache.org/plugins/maven-toolchains-plugin/[Maven Toolchains Plugin]. + +Using this plugin requires that you have a `toolchains.xml` file, typically in your +`~/.m2` folder. This file should contains at least a toolchain declaration for the +Apache UIMA minimum Java version, e.g.: + +.Example `toolchains.xml` file +---- + + + jdk + + 1.8 + + + /PATH/TO/A/JDK_1_8/INSTALLATION + + + +---- From 2a5016f2d438a80f73420da3c10404866508c220 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 23 May 2022 11:16:54 +0200 Subject: [PATCH 26/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Fix module version --- uima-doc-v3-maintainers-guide/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uima-doc-v3-maintainers-guide/pom.xml b/uima-doc-v3-maintainers-guide/pom.xml index e8109f3de1..c53d000249 100644 --- a/uima-doc-v3-maintainers-guide/pom.xml +++ b/uima-doc-v3-maintainers-guide/pom.xml @@ -25,7 +25,7 @@ org.apache.uima uimaj-parent - 3.3.0-SNAPSHOT + 3.4.0-SNAPSHOT ../uimaj-parent/pom.xml From a45b672c702fa245faac5608123787925996f612 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 23 May 2022 12:45:45 +0200 Subject: [PATCH 27/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide * Missing license header --- .../src/docs/asciidoc/uv3.maven.adoc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc index 05ff8aca30..ceed3e3c32 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.maven.adoc @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + = Maven Build This section describes various functionalities provided by the UIMA Parent POM and how to use them in downstream projects. From e8ed90b7f076a8f1aa771564f330755ddd32bbfa Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 30 May 2022 10:02:32 +0200 Subject: [PATCH 28/94] [UIMA-6459] Upgrade dependencies - UIMA Parent POM 15-SNAPSHOT -> 15 --- uimaj-parent/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index ad5551e936..f1962adcf6 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -32,7 +32,7 @@ org.apache.uima parent-pom - 15-SNAPSHOT + 15 uimaj-parent From 6ab37d2528317446e25649217e49f0a52da33a18 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 30 May 2022 10:03:56 +0200 Subject: [PATCH 29/94] [UIMA-6436] Move maintainer documentation from website into maintainer guide - Remove bullets from release checklist --- .../src/docs/asciidoc/uv3.release.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc index 3a33c2043e..a15f402da5 100644 --- a/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc +++ b/uima-doc-v3-maintainers-guide/src/docs/asciidoc/uv3.release.adoc @@ -38,6 +38,7 @@ There is no fixed release schedule. Anybody may ask for the preparation of a new === Preparations +[no-bullet] * {empty} + .Create release issue and release preparation branch @@ -126,6 +127,7 @@ NOTE: There may be a generation process involved. E.g. in the UIMA Java SDK, the === Building +[no-bullet] * {empty} + .Clean local m2 repository @@ -201,6 +203,7 @@ Note that any JARs, Zips, Tars, tar.gz artifacts must be signed by the Release M === Staging +[no-bullet] * {empty} + .Close the staging repository at http://repository.apache.org/ @@ -288,6 +291,7 @@ For a general background on how we build P2 sites, including Composite update si === Voting +[no-bullet] * {empty} + .Call for a vote on the developer mailing list using the email template below @@ -442,6 +446,7 @@ Thanks to all who voted! === Publishing +[no-bullet] * {empty} + .Copy the release artifacts from the staging spot to the dist spot in SVN From 1088f615154b385dd163965b8d2ef78e87111ab1 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 3 Jun 2022 08:35:36 +0200 Subject: [PATCH 30/94] [UIMA-6469] Cleaning up file-handling code - Introduce various constants - Use try-with-resources to more effect --- .../org/apache/uima/pear/util/FileUtil.java | 345 +++++++++--------- 1 file changed, 169 insertions(+), 176 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java b/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java index f5f430938b..3874c3129f 100644 --- a/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java +++ b/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java @@ -63,8 +63,14 @@ /** * The FileUtil class provides utility methods for working with general files. */ - public class FileUtil { + private static final String UTF8_ENCODING = "UTF-8"; + private static final String ASCII_ENCODING = "ASCII"; + private static final String XML_EXTENSION = ".xml"; + private static final String BACKUP_EXTENSION = ".bak"; + private static final String ZIP_EXTENSION = ".zip"; + private static final char UNIX_SEPARATOR = '/'; + private static final char WINDOWS_SEPARATOR = '\\'; /** * The FileTimeComparator class allows comparing 'last modified' time in 2 given @@ -116,11 +122,12 @@ public static class DirFileFilter implements FileFilter { * The given file extension. */ public DirFileFilter(String dirPath, String fileExt) { - _dirPath = (dirPath != null) ? dirPath.replace('\\', '/') : null; - if (fileExt != null) + _dirPath = (dirPath != null) ? dirPath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR) : null; + if (fileExt != null) { _fileExt = fileExt.startsWith(".") ? fileExt.toLowerCase() : "." + fileExt.toLowerCase(); - else + } else { _fileExt = null; + } } /** @@ -134,7 +141,8 @@ public boolean accept(File file) { boolean extAccepted = true; if (_dirPath != null) { String parentDir = file.getParent(); - dirAccepted = parentDir != null && parentDir.replace('\\', '/').startsWith(_dirPath); + dirAccepted = parentDir != null + && parentDir.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR).startsWith(_dirPath); } if (_fileExt != null) { extAccepted = file.getPath().toLowerCase().endsWith(_fileExt); @@ -145,7 +153,6 @@ public boolean accept(File file) { /** * The NameFileFilter class allows to filter files based on specified file name. - * */ public static class NameFileFilter implements FileFilter { // attributes @@ -158,7 +165,7 @@ public static class NameFileFilter implements FileFilter { * The given file name for filtering. */ public NameFileFilter(String fileName) { - _fileName = fileName.replace('\\', '/'); + _fileName = fileName.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); } /** @@ -168,14 +175,16 @@ public NameFileFilter(String fileName) { */ @Override public boolean accept(File file) { - String filePath = file.getAbsolutePath().replace('\\', '/'); + String filePath = file.getAbsolutePath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); if (filePath.endsWith(_fileName)) { if (filePath.length() > _fileName.length()) { char prevChar = filePath.charAt(filePath.length() - _fileName.length() - 1); - if (prevChar == ':' || prevChar == '/') + if (prevChar == ':' || prevChar == UNIX_SEPARATOR) { return true; - } else + } + } else { return true; + } } return false; } @@ -218,8 +227,9 @@ public ExtFilenameFilter(String fileExt) { public ExtFilenameFilter(String fileExt, boolean ignoreCase) { _fileExt = fileExt.startsWith(".") ? fileExt : "." + fileExt; _ignoreCase = ignoreCase; - if (ignoreCase) + if (ignoreCase) { _fileExt = _fileExt.toLowerCase(); + } } /** @@ -258,15 +268,17 @@ public static int cleanUpDirectoryContent(File directory) throws IOException { File aFile = allDirFiles[i]; if (aFile.isDirectory()) { counter += cleanUpDirectoryContent(aFile); - if (aFile.delete()) + if (aFile.delete()) { counter++; - else + } else { aFile.deleteOnExit(); + } } else if (aFile.isFile()) { - if (aFile.delete()) + if (aFile.delete()) { counter++; - else + } else { aFile.deleteOnExit(); + } } } } @@ -290,10 +302,11 @@ public static int cleanUpDirectoryFiles(File directory) throws IOException { for (int i = 0; i < allDirFiles.length; i++) { File aFile = allDirFiles[i]; if (aFile.isFile()) { - if (aFile.delete()) + if (aFile.delete()) { counter++; - else + } else { aFile.deleteOnExit(); + } } } } @@ -324,10 +337,11 @@ public static int cleanUpDirectoryFiles(File directory, int maxLimit) throws IOE File file = list.next(); no++; if (no > maxLimit) { - if (file.delete()) + if (file.delete()) { counter++; - else + } else { file.deleteOnExit(); + } } } } @@ -350,25 +364,28 @@ public static int cleanUpDirectoryFiles(File directory, int maxLimit) throws IOE */ public static String computeRelativePath(File referenceDir, File file) throws IOException { // get canonical path expressions - String refPath = referenceDir.getCanonicalPath().replace('\\', '/'); - String filePath = file.getCanonicalPath().replace('\\', '/'); + String refPath = referenceDir.getCanonicalPath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String filePath = file.getCanonicalPath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); // compute relative path from reference dir to file dir-tree StringBuffer relBuffer = new StringBuffer(); while (refPath != null && !filePath.startsWith(refPath)) { relBuffer.append("../"); refPath = (new File(refPath)).getParent(); - if (refPath != null) - refPath = refPath.replace('\\', '/'); + if (refPath != null) { + refPath = refPath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + } } if (refPath != null) { // construct relative path String subPath = filePath.substring(refPath.length()); - if (relBuffer.length() == 0) + if (relBuffer.length() == 0) { relBuffer.append("./"); - if (subPath.startsWith("/")) + } + if (subPath.startsWith("/")) { relBuffer.append(subPath.substring(1)); - else + } else { relBuffer.append(subPath); + } return relBuffer.toString(); } // relative path does not exist @@ -466,14 +483,16 @@ public static Collection createDirList(File rootDir, boolean includeSubdir throws IOException { ArrayList listOfDirs = new ArrayList<>(); File[] allDirFiles = rootDir.listFiles(); - if (allDirFiles == null) + if (allDirFiles == null) { throw new FileNotFoundException("invalid directory specified"); + } for (int i = 0; i < allDirFiles.length; i++) { File aFile = allDirFiles[i]; if (aFile.isDirectory()) { listOfDirs.add(aFile); - if (includeSubdirs) + if (includeSubdirs) { listOfDirs.addAll(createDirList(aFile, includeSubdirs)); + } } } return listOfDirs; @@ -503,14 +522,15 @@ public static Collection createDirList(JarFile archive) throws IOException while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); File file = new File(rootDir, entry.getName()); - if (entry.isDirectory()) + if (entry.isDirectory()) { listOfDirs.add(file); - else { + } else { // make sure the parent dir is added File parentDir = file.getParentFile(); while (!parentDir.equals(rootDir)) { - if (!listOfDirs.contains(parentDir)) + if (!listOfDirs.contains(parentDir)) { listOfDirs.add(parentDir); + } parentDir = parentDir.getParentFile(); } } @@ -553,14 +573,16 @@ public static Collection createFileList(File filesDir, boolean includeSubd throws IOException { ArrayList listOfFiles = new ArrayList<>(); File[] allDirFiles = filesDir.listFiles(); - if (allDirFiles == null) + if (allDirFiles == null) { throw new FileNotFoundException("invalid directory specified"); + } for (int i = 0; i < allDirFiles.length; i++) { File aFile = allDirFiles[i]; - if (aFile.isDirectory() && includeSubdirs) + if (aFile.isDirectory() && includeSubdirs) { listOfFiles.addAll(createFileList(aFile, includeSubdirs)); - else if (!aFile.isDirectory()) + } else if (!aFile.isDirectory()) { listOfFiles.add(aFile); + } } return listOfFiles; } @@ -588,8 +610,9 @@ public static Collection createFileList(JarFile archive) throws IOExceptio while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); File file = new File(rootDir, entry.getName()); - if (!entry.isDirectory()) + if (!entry.isDirectory()) { listOfFiles.add(file); + } } return listOfFiles; } @@ -614,13 +637,16 @@ public static Collection createFileList(JarFile archive) throws IOExceptio @Deprecated public static File createTempFile(String prefix, String suffix) throws IOException { String tempDirPath = System.getProperty("java.io.tmpdir"); - if (tempDirPath == null) + if (tempDirPath == null) { tempDirPath = System.getProperty("user.home"); - if (tempDirPath == null) + } + if (tempDirPath == null) { throw new IOException("could not find temporary directory"); + } File tempDir = new File(tempDirPath); - if (!tempDir.isDirectory()) + if (!tempDir.isDirectory()) { throw new IOException("temporary directory not available"); + } return File.createTempFile(prefix, suffix, tempDir); } @@ -643,9 +669,9 @@ public static boolean deleteDirectory(File dir) throws IOException { // first, delete plain files and sub-directories (recursive) for (int i = 0; i < fileList.length; i++) { File entry = fileList[i]; - if (entry.isDirectory()) + if (entry.isDirectory()) { done = deleteDirectory(entry); - else if (!entry.delete()) { + } else if (!entry.delete()) { entry.deleteOnExit(); done = false; } @@ -735,14 +761,16 @@ public static long extractFilesFromJar(JarFile jarFile, File targetDir, FileFilt JarEntry jarEntry = jarList.nextElement(); if (!jarEntry.isDirectory()) { // check that file is accepted - if (filter != null && !filter.accept(new File(jarEntry.getName()))) + if (filter != null && !filter.accept(new File(jarEntry.getName()))) { continue; + } // extract file File file = new File(targetDir, jarEntry.getName()); // make sure the file directory exists File dir = file.getParentFile(); - if (!dir.exists() && !dir.mkdirs()) + if (!dir.exists() && !dir.mkdirs()) { throw new IOException("could not create directory " + dir.getAbsolutePath()); + } try (BufferedInputStream iStream = new BufferedInputStream( jarFile.getInputStream(jarEntry)); BufferedOutputStream oStream = new BufferedOutputStream( @@ -787,10 +815,11 @@ public static String getFileNameExtension(String fileName) { buffer.append('.'); for (int i = begIndex + 1; i < fileName.length(); i++) { char ch = fileName.charAt(i); - if (Character.isLetterOrDigit(ch)) + if (Character.isLetterOrDigit(ch)) { buffer.append(ch); - else + } else { break; + } } } return buffer.toString(); @@ -809,9 +838,9 @@ public static long getFileSize(String fileLocation) { long fileSize = 0; // choose file size method: local FS or HTTP File file = new File(fileLocation); - if (file.isFile()) + if (file.isFile()) { fileSize = file.length(); - else { + } else { try { URL fileUrl = new URL(fileLocation); URLConnection urlConn = fileUrl.openConnection(); @@ -836,12 +865,14 @@ public static long getFileSize(String fileLocation) { * @return The relative path of the given object, located in the given root directory. */ public static String getRelativePath(File rootDir, String absolutePath) { - String rootDirPath = rootDir.getAbsolutePath().replace('\\', '/'); - String objectPath = absolutePath.replace('\\', '/'); - if (objectPath.startsWith(rootDirPath)) + String rootDirPath = rootDir.getAbsolutePath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String objectPath = absolutePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + if (objectPath.startsWith(rootDirPath)) { objectPath = objectPath.substring(rootDirPath.length()); - if (objectPath.startsWith("/")) + } + if (objectPath.startsWith("/")) { objectPath = objectPath.substring(1); + } return objectPath; } @@ -861,20 +892,23 @@ public static String identifyUtfSignature(int[] prefix, int length) { String utfSignature = null; if (length == 3) { // check for UTF-8 signature - if (prefix[0] == 0xEF && prefix[1] == 0xBB && prefix[2] == 0xBF) - utfSignature = "UTF-8"; + if (prefix[0] == 0xEF && prefix[1] == 0xBB && prefix[2] == 0xBF) { + utfSignature = UTF8_ENCODING; + } } else if (length == 2) { // check for UTF-16 signature - if (prefix[0] == 0xFE && prefix[1] == 0xFF) + if (prefix[0] == 0xFE && prefix[1] == 0xFF) { utfSignature = "UTF-16BE"; - else if (prefix[0] == 0xFF && prefix[1] == 0xFE) + } else if (prefix[0] == 0xFF && prefix[1] == 0xFE) { utfSignature = "UTF-16LE"; + } } else if (length == 4) { // check for UTF-32 signature - if (prefix[0] == 0x00 && prefix[1] == 0x00 && prefix[2] == 0xFE && prefix[3] == 0xFF) + if (prefix[0] == 0x00 && prefix[1] == 0x00 && prefix[2] == 0xFE && prefix[3] == 0xFF) { utfSignature = "UTF-32BE"; - else if (prefix[0] == 0xFF && prefix[1] == 0xFE && prefix[2] == 0x00 && prefix[3] == 0x00) + } else if (prefix[0] == 0xFF && prefix[1] == 0xFE && prefix[2] == 0x00 && prefix[3] == 0x00) { utfSignature = "UTF-32LE"; + } } return utfSignature; } @@ -891,23 +925,9 @@ else if (prefix[0] == 0xFF && prefix[1] == 0xFE && prefix[2] == 0x00 && prefix[3 * If an I/O exception occurred. */ public static boolean isAsciiFile(File textFile) throws IOException { - boolean isAscii = true; - FileInputStream iStream = null; - try { - iStream = new FileInputStream(textFile); - isAscii = isAsciiStream(iStream); - iStream.close(); - } catch (IOException exc) { - isAscii = false; - throw exc; - } finally { - if (iStream != null) - try { - iStream.close(); - } catch (Exception e) { - } + try (FileInputStream iStream = new FileInputStream(textFile)) { + return isAsciiStream(iStream); } - return isAscii; } /** @@ -923,17 +943,12 @@ public static boolean isAsciiFile(File textFile) throws IOException { */ public static boolean isAsciiStream(InputStream iStream) throws IOException { boolean isAscii = true; - try { - int nextByte = 0; - while ((nextByte = iStream.read()) >= 0) { - if (nextByte > 127) { - isAscii = false; - break; - } + int nextByte = 0; + while ((nextByte = iStream.read()) >= 0) { + if (nextByte > 127) { + isAscii = false; + break; } - } catch (IOException exc) { - isAscii = false; - throw exc; } return isAscii; } @@ -953,8 +968,9 @@ public static String[] loadListOfStrings(BufferedReader iStream) throws IOExcept String line = null; while ((line = iStream.readLine()) != null) { String string = line.trim(); - if (string.length() > 0) + if (string.length() > 0) { outputList.add(string); + } } if (outputList.size() > 0) { outputArray = new String[outputList.size()]; @@ -1021,7 +1037,7 @@ public static String[] loadListOfStrings(URL textFileURL) throws IOException { public static Properties loadPropertiesFromJar(String propFilePath, JarFile jarFile) throws IOException { Properties properties = null; - String name = propFilePath.replace('\\', '/'); + String name = propFilePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); JarEntry jarEntry = jarFile.getJarEntry(name); if (jarEntry != null) { try (InputStream iStream = jarFile.getInputStream(jarEntry)) { @@ -1042,26 +1058,13 @@ public static Properties loadPropertiesFromJar(String propFilePath, JarFile jarF * If any I/O exception occurs. */ public static String loadTextFile(BufferedReader iStream) throws IOException { - StringWriter buffer = null; - PrintWriter writer = null; - try { - buffer = new StringWriter(); - writer = new PrintWriter(buffer); + try (StringWriter buffer = new StringWriter(); PrintWriter writer = new PrintWriter(buffer);) { String line = null; - while ((line = iStream.readLine()) != null) + while ((line = iStream.readLine()) != null) { writer.println(line); - writer.flush(); - } catch (IOException exc) { - throw exc; - } finally { - if (writer != null) { - try { - writer.close(); - } catch (Exception e) { - } } + return buffer.toString(); } - return buffer.toString(); } /** @@ -1078,11 +1081,9 @@ public static String loadTextFile(BufferedReader iStream) throws IOException { */ @Deprecated public static String loadTextFile(File textFile) throws IOException { - String content; try (BufferedReader iStream = new BufferedReader(new FileReader(textFile))) { - content = loadTextFile(iStream); + return loadTextFile(iStream); } - return content; } /** @@ -1155,7 +1156,7 @@ public static String loadTextFile(URLConnection urlConnection) throws IOExceptio */ public static String loadTextFileFromJar(String filePath, JarFile jarFile) throws IOException { String content = null; - String name = filePath.replace('\\', '/'); + String name = filePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); JarEntry jarEntry = jarFile.getJarEntry(name); if (jarEntry != null) { try (BufferedReader iStream = new BufferedReader( @@ -1176,7 +1177,7 @@ public static String loadTextFileFromJar(String filePath, JarFile jarFile) throw public static String localPathToFileUrl(String path) { // get absolute path File file = new File(path); - String absPath = file.getAbsolutePath().replace('\\', '/'); + String absPath = file.getAbsolutePath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); // construct file URL StringBuffer urlBuffer = new StringBuffer("file:///"); urlBuffer.append(absPath.replace(':', '|')); @@ -1207,8 +1208,9 @@ public static String localPathToFileUrl(String path) { public static boolean moveFile(File source, File destinationDir) throws IOException { boolean completed = false; File destination = new File(destinationDir, source.getName()); - if (destination.exists()) + if (destination.exists()) { destination.delete(); + } if (copyFile(source, destination)) { completed = source.delete(); } @@ -1234,23 +1236,22 @@ public static int replaceStringInFile(File textFile, String subStringRegex, Stri throws IOException { int counter = 0; // for general text file - supporting ASCII encoding only - String encoding = "ASCII"; + String encoding = ASCII_ENCODING; // check file extension int extIndex = textFile.getName().lastIndexOf('.'); String fileExt = (extIndex > 0) ? textFile.getName().substring(extIndex) : null; - if (".xml".equalsIgnoreCase(fileExt)) { + if (XML_EXTENSION.equalsIgnoreCase(fileExt)) { // for XML file - supporting UTF-8 (ASCII) and UTF-16 encodings String xmlEncoding = XMLUtil.detectXmlFileEncoding(textFile); if (xmlEncoding != null) { encoding = xmlEncoding; } else { - encoding = "UTF-8"; + encoding = UTF8_ENCODING; } } // load text file, using supported encoding String fileContent = loadTextFile(textFile, encoding); - BufferedReader sReader = null; - PrintStream fStream = null; + boolean done = false; File backupFile = null; // get pattern for given regex @@ -1259,51 +1260,48 @@ public static int replaceStringInFile(File textFile, String subStringRegex, Stri String replaceWith = StringUtil.toRegExpReplacement(replacement); try { // save backup copy of input file - backupFile = new File(textFile.getAbsolutePath() + ".bak"); - if (backupFile.exists()) + backupFile = new File(textFile.getAbsolutePath() + BACKUP_EXTENSION); + if (backupFile.exists()) { backupFile.delete(); - if (!textFile.renameTo(backupFile)) + } + if (!textFile.renameTo(backupFile)) { throw new IOException("can't save backup copy of " + textFile.getAbsolutePath()); - sReader = new BufferedReader(new StringReader(fileContent)); - fStream = new PrintStream(new FileOutputStream(textFile), true, encoding); - String srcLine = null; - while ((srcLine = sReader.readLine()) != null) { - // count pattern matches in the source string - Matcher matcher = pattern.matcher(srcLine); - while (matcher.find()) - counter++; - // replace all pattern matches in the source string - String resLine = srcLine.replaceAll(subStringRegex, replaceWith); - fStream.println(resLine); } - fStream.close(); + try (BufferedReader sReader = new BufferedReader(new StringReader(fileContent)); + PrintStream fStream = new PrintStream(new FileOutputStream(textFile), true, + encoding);) { + String srcLine = null; + while ((srcLine = sReader.readLine()) != null) { + // count pattern matches in the source string + Matcher matcher = pattern.matcher(srcLine); + while (matcher.find()) { + counter++; + } + // replace all pattern matches in the source string + String resLine = srcLine.replaceAll(subStringRegex, replaceWith); + fStream.println(resLine); + } + } done = true; } catch (IOException exc) { throw exc; } catch (Throwable err) { - if (err instanceof IOException) + if (err instanceof IOException) { throw new IOException(err.toString() + " in " + textFile.getAbsolutePath()); + } throw new RuntimeException(err.toString() + " in " + textFile.getAbsolutePath()); } finally { - if (sReader != null) { - try { - sReader.close(); - } catch (Exception e) { - } - } - if (fStream != null) { - try { - fStream.close(); - } catch (Exception e) { - } - } if (done) { // remove backup file - backupFile.delete(); + if (backupFile != null) { + backupFile.delete(); + } } else { // restore input file textFile.delete(); - backupFile.renameTo(textFile); + if (backupFile != null) { + backupFile.renameTo(textFile); + } } } return counter; @@ -1334,7 +1332,7 @@ public static SortedSet sortFileListByTime(Collection fileList) { */ public static File zipDirectory(File dir2zip) throws IOException { // construct zipped file path - String zipFileName = dir2zip.getName() + ".zip"; + String zipFileName = dir2zip.getName() + ZIP_EXTENSION; File zipFile = new File(dir2zip, zipFileName); return zipDirectory(dir2zip, zipFile); } @@ -1383,27 +1381,27 @@ public static ZipOutputStream zipDirectory(File dir2zip, ZipOutputStream zoStrea File referenceDir, File[] excludeFiles) throws IOException { byte[] block = new byte[4096]; int inBytes = 0; - FileInputStream iStream = null; - try { - // get list of all files/dirs in the given directory - File[] dirFileList = dir2zip.listFiles(); - // compress all files and sub-dirs - for (int i = 0; i < dirFileList.length; i++) { - File entry = dirFileList[i]; - // check if this entry is not in the list of exclusions - boolean isExcluded = false; - for (int n = 0; n < excludeFiles.length; n++) { - if (entry.equals(excludeFiles[n])) { - isExcluded = true; - break; - } + + // get list of all files/dirs in the given directory + File[] dirFileList = dir2zip.listFiles(); + // compress all files and sub-dirs + for (int i = 0; i < dirFileList.length; i++) { + File entry = dirFileList[i]; + // check if this entry is not in the list of exclusions + boolean isExcluded = false; + for (int n = 0; n < excludeFiles.length; n++) { + if (entry.equals(excludeFiles[n])) { + isExcluded = true; + break; } - if (isExcluded) - continue; - // for each file - add ZipEntry and compress the file - if (entry.isFile()) { - // open input stream - iStream = new FileInputStream(entry); + } + if (isExcluded) { + continue; + } + // for each file - add ZipEntry and compress the file + if (entry.isFile()) { + // open input stream + try (FileInputStream iStream = new FileInputStream(entry)) { // put ZipEntry for the file String zipEntryName = (referenceDir != null) ? getRelativePath(referenceDir, entry.getAbsolutePath()) @@ -1411,21 +1409,15 @@ public static ZipOutputStream zipDirectory(File dir2zip, ZipOutputStream zoStrea ZipEntry zipEntry = new ZipEntry(zipEntryName); zoStream.putNextEntry(zipEntry); // read input stream and write to output stream - while ((inBytes = iStream.read(block)) > 0) + while ((inBytes = iStream.read(block)) > 0) { zoStream.write(block, 0, inBytes); - // close input stream - iStream.close(); - } else if (entry.isDirectory()) // zip sub-dir recursively - zipDirectory(entry, zoStream, referenceDir, excludeFiles); - } - } finally { - if (iStream != null) { - try { - iStream.close(); - } catch (Exception e) { + } } + } else if (entry.isDirectory()) { // zip sub-dir recursively + zipDirectory(entry, zoStream, referenceDir, excludeFiles); } } + return zoStream; } @@ -1443,8 +1435,8 @@ public static File zipFile(File file2zip) throws IOException { // construct zipped file path String zipFileName = file2zip.getName(); int extIndex = zipFileName.lastIndexOf('.'); - zipFileName = (extIndex >= 0) ? zipFileName.substring(0, extIndex) + ".zip" - : zipFileName + ".zip"; + zipFileName = (extIndex >= 0) ? zipFileName.substring(0, extIndex) + ZIP_EXTENSION + : zipFileName + ZIP_EXTENSION; File zipFile = new File(file2zip.getParentFile(), zipFileName); return zipFile(file2zip, zipFile); } @@ -1475,8 +1467,9 @@ public static File zipFile(File file2zip, File zippedFile) throws IOException { // add new ZipEntry oStream.putNextEntry(zipEntry); // read input stream and write to output stream - while ((inBytes = iStream.read(block)) > 0) + while ((inBytes = iStream.read(block)) > 0) { oStream.write(block, 0, inBytes); + } } finally { if (iStream != null) { try { From 7aab4a82a7c0cc8f79476b60e86a15037ee2ea98 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 3 Jun 2022 08:37:35 +0200 Subject: [PATCH 31/94] [UIMA-6469] Cleaning up file-handling code - Formatting --- .../uima/resource/impl/RelativePathResolver_impl.java | 2 +- .../uima/resource/impl/RelativePathResolver_implTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java b/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java index 3929124148..789dd25f29 100644 --- a/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java +++ b/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java @@ -112,7 +112,7 @@ public void setDataPathElements(File... aPaths) throws MalformedURLException { mDataPath = unmodifiableList(Arrays.stream(aPaths) // .map(File::getPath) // - .map(s-> s.replace(File.separator, "/")) + .map(s -> s.replace(File.separator, "/")) // .collect(toList())); mBaseUrls = new URL[aPaths.length]; for (int i = 0; i < aPaths.length; i++) { diff --git a/uimaj-core/src/test/java/org/apache/uima/resource/impl/RelativePathResolver_implTest.java b/uimaj-core/src/test/java/org/apache/uima/resource/impl/RelativePathResolver_implTest.java index 057ae2d4f4..c099fef717 100644 --- a/uimaj-core/src/test/java/org/apache/uima/resource/impl/RelativePathResolver_implTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/resource/impl/RelativePathResolver_implTest.java @@ -38,8 +38,8 @@ public class RelativePathResolver_implTest { private final static String PATH_SEP = System.getProperty("path.separator"); private RelativePathResolver_impl sut; - private final static String element1 = "/this/is/a/test"; - private final static String element2 = "/another/test" ; + private final static String element1 = "/this/is/a/test"; + private final static String element2 = "/another/test"; private final static String[] expectedElements = { element1, element2 }; private final static String expectedPath = String.join(PATH_SEP, expectedElements); @@ -105,7 +105,7 @@ public void testResolveRelativePath() throws Exception { @SuppressWarnings("deprecation") private void assertThatGettersReturnTheRightValues(RelativePathResolver_impl aResolver) { - + assertThat(aResolver.getDataPathElements()) // .containsExactly(expectedElements); From 9c99e071be79bdb6bbd1bcd3f20431d76ce5143e Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 3 Jun 2022 10:03:52 +0200 Subject: [PATCH 32/94] [UIMA-6469] Cleaning up file-handling code - Modernize and extend tests - More constants instead of magic strings - Centralize normalization of paths to unix paths - Improve JAR extraction handling - More try-with-resources --- .../org/apache/uima/pear/util/FileUtil.java | 145 ++++++++++-------- .../org/apache/uima/util/FileUtilsTest.java | 35 +++-- 2 files changed, 103 insertions(+), 77 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java b/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java index 3874c3129f..ae18a1a10e 100644 --- a/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java +++ b/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java @@ -64,13 +64,16 @@ * The FileUtil class provides utility methods for working with general files. */ public class FileUtil { + private static final char DOT = '.'; private static final String UTF8_ENCODING = "UTF-8"; private static final String ASCII_ENCODING = "ASCII"; - private static final String XML_EXTENSION = ".xml"; - private static final String BACKUP_EXTENSION = ".bak"; - private static final String ZIP_EXTENSION = ".zip"; - private static final char UNIX_SEPARATOR = '/'; - private static final char WINDOWS_SEPARATOR = '\\'; + private static final String XML_EXTENSION = DOT + "xml"; + private static final String BACKUP_EXTENSION = DOT + "bak"; + private static final String ZIP_EXTENSION = DOT + "zip"; + private static final char UNIX_SEPARATOR_CHAR = '/'; + private static final char WINDOWS_SEPARATOR_CHAR = '\\'; + private static final String UNIX_SEPARATOR = String.valueOf(UNIX_SEPARATOR_CHAR); + private static final String WINDOWS_SEPARATOR = String.valueOf(WINDOWS_SEPARATOR_CHAR); /** * The FileTimeComparator class allows comparing 'last modified' time in 2 given @@ -122,7 +125,8 @@ public static class DirFileFilter implements FileFilter { * The given file extension. */ public DirFileFilter(String dirPath, String fileExt) { - _dirPath = (dirPath != null) ? dirPath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR) : null; + _dirPath = (dirPath != null) ? dirPath.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR) + : null; if (fileExt != null) { _fileExt = fileExt.startsWith(".") ? fileExt.toLowerCase() : "." + fileExt.toLowerCase(); } else { @@ -142,7 +146,8 @@ public boolean accept(File file) { if (_dirPath != null) { String parentDir = file.getParent(); dirAccepted = parentDir != null - && parentDir.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR).startsWith(_dirPath); + && parentDir.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR) + .startsWith(_dirPath); } if (_fileExt != null) { extAccepted = file.getPath().toLowerCase().endsWith(_fileExt); @@ -165,7 +170,7 @@ public static class NameFileFilter implements FileFilter { * The given file name for filtering. */ public NameFileFilter(String fileName) { - _fileName = fileName.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + _fileName = fileName.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR); } /** @@ -175,11 +180,11 @@ public NameFileFilter(String fileName) { */ @Override public boolean accept(File file) { - String filePath = file.getAbsolutePath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String filePath = file.getAbsolutePath().replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR); if (filePath.endsWith(_fileName)) { if (filePath.length() > _fileName.length()) { char prevChar = filePath.charAt(filePath.length() - _fileName.length() - 1); - if (prevChar == ':' || prevChar == UNIX_SEPARATOR) { + if (prevChar == ':' || prevChar == UNIX_SEPARATOR_CHAR) { return true; } } else { @@ -348,6 +353,14 @@ public static int cleanUpDirectoryFiles(File directory, int maxLimit) throws IOE return counter; } + private static String normalizeToUnix(String aPath) { + if (aPath == null) { + return null; + } + + return aPath.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR); + } + /** * Computes relative path to a given file from a given reference directory, if both the reference * directory and the file are in the same logical file system (partition). @@ -364,17 +377,15 @@ public static int cleanUpDirectoryFiles(File directory, int maxLimit) throws IOE */ public static String computeRelativePath(File referenceDir, File file) throws IOException { // get canonical path expressions - String refPath = referenceDir.getCanonicalPath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); - String filePath = file.getCanonicalPath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String refPath = normalizeToUnix(referenceDir.getCanonicalPath()); + String filePath = normalizeToUnix(file.getCanonicalPath()); // compute relative path from reference dir to file dir-tree StringBuffer relBuffer = new StringBuffer(); while (refPath != null && !filePath.startsWith(refPath)) { relBuffer.append("../"); - refPath = (new File(refPath)).getParent(); - if (refPath != null) { - refPath = refPath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); - } + refPath = normalizeToUnix((new File(refPath)).getParent()); } + if (refPath != null) { // construct relative path String subPath = filePath.substring(refPath.length()); @@ -513,7 +524,7 @@ public static Collection createDirList(File rootDir, boolean includeSubdir public static Collection createDirList(JarFile archive) throws IOException { ArrayList listOfDirs = new ArrayList<>(); // set root_dir_path = archive_file_path (w/o file name extension) - int nameEndIndex = archive.getName().lastIndexOf('.'); + int nameEndIndex = archive.getName().lastIndexOf(DOT); String rootDirPath = (nameEndIndex > 0) ? archive.getName().substring(0, nameEndIndex) : archive.getName(); File rootDir = new File(rootDirPath); @@ -601,7 +612,7 @@ public static Collection createFileList(File filesDir, boolean includeSubd public static Collection createFileList(JarFile archive) throws IOException { ArrayList listOfFiles = new ArrayList<>(); // set root_dir_path = archive_file_path (w/o file name extension) - int nameEndIndex = archive.getName().lastIndexOf('.'); + int nameEndIndex = archive.getName().lastIndexOf(DOT); String rootDirPath = (nameEndIndex > 0) ? archive.getName().substring(0, nameEndIndex) : archive.getName(); File rootDir = new File(rootDirPath); @@ -756,33 +767,49 @@ public static long extractFilesFromJar(JarFile jarFile, File targetDir, FileFilt throws IOException { long totalBytes = 0; byte[] block = new byte[4096]; + + String prefix = normalizeToUnix(targetDir.getCanonicalPath()); + if (!prefix.endsWith(UNIX_SEPARATOR)) { + prefix = prefix + UNIX_SEPARATOR_CHAR; + } + Enumeration jarList = jarFile.entries(); while (jarList.hasMoreElements()) { JarEntry jarEntry = jarList.nextElement(); - if (!jarEntry.isDirectory()) { - // check that file is accepted - if (filter != null && !filter.accept(new File(jarEntry.getName()))) { - continue; - } - // extract file - File file = new File(targetDir, jarEntry.getName()); - // make sure the file directory exists - File dir = file.getParentFile(); - if (!dir.exists() && !dir.mkdirs()) { - throw new IOException("could not create directory " + dir.getAbsolutePath()); - } - try (BufferedInputStream iStream = new BufferedInputStream( - jarFile.getInputStream(jarEntry)); - BufferedOutputStream oStream = new BufferedOutputStream( - new FileOutputStream(file))) { - int bCount = 0; - while ((bCount = iStream.read(block)) > 0) { - totalBytes += bCount; - oStream.write(block, 0, bCount); - } + if (jarEntry.isDirectory()) { + continue; + } + + // check that file is accepted + if (filter != null && !filter.accept(new File(jarEntry.getName()))) { + continue; + } + + // make sure the file directory exists + File file = new File(targetDir, jarEntry.getName()); + + if (!normalizeToUnix(file.getCanonicalPath()).startsWith(prefix)) { + throw new IOException( + "Can only write within target folder [" + targetDir.getAbsolutePath() + + "]. Please validate ZIP contents."); + } + + File dir = file.getParentFile(); + if (!dir.exists() && !dir.mkdirs()) { + throw new IOException("Could not create directory [" + dir.getAbsolutePath() + "]"); + } + + // extract file + try (BufferedInputStream iStream = new BufferedInputStream(jarFile.getInputStream(jarEntry)); + BufferedOutputStream oStream = new BufferedOutputStream(new FileOutputStream(file))) { + int bCount = 0; + while ((bCount = iStream.read(block)) > 0) { + totalBytes += bCount; + oStream.write(block, 0, bCount); } } } + return totalBytes; } @@ -810,9 +837,9 @@ public static String getAbsolutePath(File rootDir, String relativePath) { */ public static String getFileNameExtension(String fileName) { StringBuffer buffer = new StringBuffer(); - int begIndex = fileName.lastIndexOf('.'); + int begIndex = fileName.lastIndexOf(DOT); if (begIndex > 0) { - buffer.append('.'); + buffer.append(DOT); for (int i = begIndex + 1; i < fileName.length(); i++) { char ch = fileName.charAt(i); if (Character.isLetterOrDigit(ch)) { @@ -865,8 +892,8 @@ public static long getFileSize(String fileLocation) { * @return The relative path of the given object, located in the given root directory. */ public static String getRelativePath(File rootDir, String absolutePath) { - String rootDirPath = rootDir.getAbsolutePath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); - String objectPath = absolutePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String rootDirPath = normalizeToUnix(rootDir.getAbsolutePath()); + String objectPath = normalizeToUnix(absolutePath); if (objectPath.startsWith(rootDirPath)) { objectPath = objectPath.substring(rootDirPath.length()); } @@ -1037,7 +1064,7 @@ public static String[] loadListOfStrings(URL textFileURL) throws IOException { public static Properties loadPropertiesFromJar(String propFilePath, JarFile jarFile) throws IOException { Properties properties = null; - String name = propFilePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String name = normalizeToUnix(propFilePath); JarEntry jarEntry = jarFile.getJarEntry(name); if (jarEntry != null) { try (InputStream iStream = jarFile.getInputStream(jarEntry)) { @@ -1156,7 +1183,7 @@ public static String loadTextFile(URLConnection urlConnection) throws IOExceptio */ public static String loadTextFileFromJar(String filePath, JarFile jarFile) throws IOException { String content = null; - String name = filePath.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String name = normalizeToUnix(filePath); JarEntry jarEntry = jarFile.getJarEntry(name); if (jarEntry != null) { try (BufferedReader iStream = new BufferedReader( @@ -1177,7 +1204,7 @@ public static String loadTextFileFromJar(String filePath, JarFile jarFile) throw public static String localPathToFileUrl(String path) { // get absolute path File file = new File(path); - String absPath = file.getAbsolutePath().replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR); + String absPath = normalizeToUnix(file.getAbsolutePath()); // construct file URL StringBuffer urlBuffer = new StringBuffer("file:///"); urlBuffer.append(absPath.replace(':', '|')); @@ -1238,7 +1265,7 @@ public static int replaceStringInFile(File textFile, String subStringRegex, Stri // for general text file - supporting ASCII encoding only String encoding = ASCII_ENCODING; // check file extension - int extIndex = textFile.getName().lastIndexOf('.'); + int extIndex = textFile.getName().lastIndexOf(DOT); String fileExt = (extIndex > 0) ? textFile.getName().substring(extIndex) : null; if (XML_EXTENSION.equalsIgnoreCase(fileExt)) { // for XML file - supporting UTF-8 (ASCII) and UTF-16 encodings @@ -1434,7 +1461,7 @@ public static ZipOutputStream zipDirectory(File dir2zip, ZipOutputStream zoStrea public static File zipFile(File file2zip) throws IOException { // construct zipped file path String zipFileName = file2zip.getName(); - int extIndex = zipFileName.lastIndexOf('.'); + int extIndex = zipFileName.lastIndexOf(DOT); zipFileName = (extIndex >= 0) ? zipFileName.substring(0, extIndex) + ZIP_EXTENSION : zipFileName + ZIP_EXTENSION; File zipFile = new File(file2zip.getParentFile(), zipFileName); @@ -1455,34 +1482,16 @@ public static File zipFile(File file2zip) throws IOException { public static File zipFile(File file2zip, File zippedFile) throws IOException { byte[] block = new byte[4096]; int inBytes = 0; - FileInputStream iStream = null; - ZipOutputStream oStream = null; - try { - // open input stream - iStream = new FileInputStream(file2zip); + try (FileInputStream iStream = new FileInputStream(file2zip); + ZipOutputStream oStream = new ZipOutputStream(new FileOutputStream(zippedFile));) { // create ZipEntry, using input file name ZipEntry zipEntry = new ZipEntry(file2zip.getName()); - // open compressed output stream - oStream = new ZipOutputStream(new FileOutputStream(zippedFile)); // add new ZipEntry oStream.putNextEntry(zipEntry); // read input stream and write to output stream while ((inBytes = iStream.read(block)) > 0) { oStream.write(block, 0, inBytes); } - } finally { - if (iStream != null) { - try { - iStream.close(); - } catch (Exception e) { - } - } - if (oStream != null) { - try { - oStream.close(); - } catch (Exception e) { - } - } } return zippedFile; } diff --git a/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java b/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java index d706859280..7834f275de 100644 --- a/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java @@ -18,13 +18,21 @@ */ package org.apache.uima.util; +import static org.apache.uima.pear.util.FileUtil.extractFilesFromJar; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Path; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; public class FileUtilsTest { @Test @@ -45,12 +53,8 @@ public void testFindRelativePath() throws Exception { } @Test - public void testReadWriteTempFile() throws IOException { - final String tmpDirPath = System.getProperty("java.io.tmpdir"); - assertNotNull("java.io.tmpdir system property not available", tmpDirPath); - File tmpDir = FileUtils.createTempDir(new File(tmpDirPath), "fileUtilsTest"); - File tmpFile1 = FileUtils.createTempFile("test", null, tmpDir); - File tmpFile2 = FileUtils.createTempFile("test", null, tmpDir); + public void testReadWriteTempFile(@TempDir Path aTempDir) throws IOException { + File tmpFile2 = aTempDir.resolve("file2.txt").toFile(); final String text = "This is some text to test file writing. Add an Umlaut for encoding tests:" + "\n Greetings from T\u00FCbingen!\n"; final String utf8 = "UTF-8"; @@ -61,8 +65,21 @@ public void testReadWriteTempFile() throws IOException { // assertEquals(text, FileUtils.file2String(tmpFile1)); FileUtils.saveString2File(text, tmpFile2, utf8); - assertEquals(text, FileUtils.file2String(tmpFile2, utf8)); + assertThat(FileUtils.file2String(tmpFile2, utf8)).isEqualTo(text); + } + + @Test + void thatAllFilesGoToTargetFolder(@TempDir Path aTempDir) throws Exception { + File zipFile = aTempDir.resolve("test.zip").toFile(); + + try (ZipOutputStream oStream = new ZipOutputStream(new FileOutputStream(zipFile))) { + ZipEntry zipEntry = new ZipEntry("../whoops.txt"); + oStream.putNextEntry(zipEntry); + } - FileUtils.deleteRecursive(tmpDir); + File target = aTempDir.resolve("target").toFile(); + assertThatExceptionOfType(IOException.class) + .isThrownBy(() -> extractFilesFromJar(new JarFile(zipFile), target)) + .withMessageContaining("Can only write within target folder"); } } From 17684f6a0863d446f8db7ee404f15a56cac129f3 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 3 Jun 2022 10:35:42 +0200 Subject: [PATCH 33/94] [UIMA-6469] Cleaning up file-handling code - Close file in test --- .../test/java/org/apache/uima/util/FileUtilsTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java b/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java index 7834f275de..9c1b60ada7 100644 --- a/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/util/FileUtilsTest.java @@ -78,8 +78,11 @@ void thatAllFilesGoToTargetFolder(@TempDir Path aTempDir) throws Exception { } File target = aTempDir.resolve("target").toFile(); - assertThatExceptionOfType(IOException.class) - .isThrownBy(() -> extractFilesFromJar(new JarFile(zipFile), target)) - .withMessageContaining("Can only write within target folder"); + + try (JarFile jarFile = new JarFile(zipFile)) { + assertThatExceptionOfType(IOException.class) + .isThrownBy(() -> extractFilesFromJar(jarFile, target)) + .withMessageContaining("Can only write within target folder"); + } } } From 6fa6bdc6e848089304fc826ed1fb59c1286d79de Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 8 Jun 2022 13:21:32 +0200 Subject: [PATCH 34/94] [No Jira] Update auto-formatting settings --- src/main/eclipse/org.eclipse.jdt.core.prefs | 9 +++++++++ src/main/eclipse/org.eclipse.jdt.ui.prefs | 2 +- .../src/main/java/org/apache/uima/util/CasIOUtils.java | 1 - 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/eclipse/org.eclipse.jdt.core.prefs b/src/main/eclipse/org.eclipse.jdt.core.prefs index 9ed6a9e542..d92babdabc 100644 --- a/src/main/eclipse/org.eclipse.jdt.core.prefs +++ b/src/main/eclipse/org.eclipse.jdt.core.prefs @@ -12,6 +12,7 @@ org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false org.eclipse.jdt.core.formatter.align_with_spaces=false @@ -39,6 +40,8 @@ org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon=0 org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 @@ -57,6 +60,7 @@ org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow=0 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 @@ -180,6 +184,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arg org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert @@ -271,6 +276,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_ar org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert @@ -354,6 +360,8 @@ org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line=one_line_never org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never org.eclipse.jdt.core.formatter.lineSplit=100 @@ -394,5 +402,6 @@ org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator=false org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/src/main/eclipse/org.eclipse.jdt.ui.prefs b/src/main/eclipse/org.eclipse.jdt.ui.prefs index 10948b0cae..7928b7c649 100644 --- a/src/main/eclipse/org.eclipse.jdt.ui.prefs +++ b/src/main/eclipse/org.eclipse.jdt.ui.prefs @@ -1,7 +1,7 @@ eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_Apache UIMA Code Conventions -formatter_settings_version=21 +formatter_settings_version=22 sp_cleanup.add_all=false sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false diff --git a/uimaj-core/src/main/java/org/apache/uima/util/CasIOUtils.java b/uimaj-core/src/main/java/org/apache/uima/util/CasIOUtils.java index 5d60cbe4b8..25657138c2 100644 --- a/uimaj-core/src/main/java/org/apache/uima/util/CasIOUtils.java +++ b/uimaj-core/src/main/java/org/apache/uima/util/CasIOUtils.java @@ -625,5 +625,4 @@ private static void closeQuitely(Closeable closeable) { } } } - } \ No newline at end of file From 4b5dcd53984a26a71e296be57702e4d4959e6b96 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 8 Jun 2022 13:22:50 +0200 Subject: [PATCH 35/94] [No Jira] Avoid triggering auto-staging as part of snapshot deployment --- Jenkinsfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7d2ed34788..1490175aef 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -18,7 +18,5 @@ @Library('uima-build-jenkins-shared-library') _ defaultPipeline { - // The Eclipse libraries that our plugins depend unfortunately on required Java 11 - jdk = 'jdk_11_latest' - extraMavenArguments = '-Pjacoco,pmd,run-rat-report' + extraMavenArguments = '-Pjacoco,spotbugs,pmd,run-rat-report -Ddisable-rc-auto-staging' } From 637f15c989ecc0975dec381f7f38602384873591 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 8 Jun 2022 14:56:50 +0200 Subject: [PATCH 36/94] [No Jira] Temporarily update spotbugs to be compatible with Java 17 until we go to Parent POM 16 --- uimaj-parent/pom.xml | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index 83d4035730..0ae4f1eedd 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -42,6 +42,13 @@ The common parent pom for the UIMA Java SDK ${uimaWebsiteUrl} + + uimaj-3.2.0 + scm:git:https://github.com/apache/uima-uimaj/ + scm:git:https://github.com/apache/uima-uimaj/ + https://github.com/apache/uima-uimaj/ + + - + 4.0.0 @@ -246,6 +248,12 @@ + + com.github.spotbugs + spotbugs-maven-plugin + 4.7.0.0 + + com.github.siom79.japicmp @@ -395,20 +403,5 @@ - - - spotbugs - - - - - com.github.spotbugs - spotbugs-maven-plugin - 4.7.0.0 - - - - - From 470aeee80730bf9d064024f82b8aeb7c43c98c7b Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 8 Jun 2022 19:15:11 +0200 Subject: [PATCH 38/94] [UIMA-6463] Use toolchains to ensure compatibility with Java 1.8 - Add toolchain configuration to parent POM --- uimaj-parent/pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index a6fd7c3c73..eebd19a201 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -248,6 +248,25 @@ + + org.apache.maven.plugins + maven-toolchains-plugin + + + + toolchain + + + + + + + ${maven.compiler.target} + + + + + com.github.spotbugs spotbugs-maven-plugin From 849ace5f51554c8275463a721d97cc8ea8c0c3dd Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 22 Jun 2022 08:52:37 +0200 Subject: [PATCH 39/94] [No Jira] Remove outdated figure - Removing old version of the annotation predicates figure which is not used - there is already a new version in the repo --- .../annotation-relations.png | Bin 328700 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 uima-doc-v3-users-guide/src/docs/asciidoc/images/version_3_users_guide/annotation_predicates/annotation-relations.png diff --git a/uima-doc-v3-users-guide/src/docs/asciidoc/images/version_3_users_guide/annotation_predicates/annotation-relations.png b/uima-doc-v3-users-guide/src/docs/asciidoc/images/version_3_users_guide/annotation_predicates/annotation-relations.png deleted file mode 100644 index ed0ff6d96c370b2749ff661e9cfe762a0c62bf93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 328700 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 z

2GYNbX?EtlD7I<9_r^n7Q7^rM@E)o6B{htMj;mQ-Brz8W8?N7~Y4#cSOg=1+(B zk3-9nc57-hoU9TrlkKN*nD&e?8>CpBal4Q;`dYn{K!LkXO!){Tf%ifpv~aWywua0& zKaP5B;Mk2FPLpYn$&(p+*0?6mcsxUWH4`MsUKS_K9dy9W|5R+3gm7#pYdoZcoh;qHg|*aPUy| zsMxG>W;c9)?o|k!$UckeZYOjMA44II@ZWA()U%-c!t+Ma{#)W<|RJ&;n zy94CHX=L7i)wqASR!a~q`S;8NXeVM`L2m^vee_uDP=Ecu4SQy|e1xoz&EaCk; zOTV)5UO&$g%bMFXI7>xy=(9wJK1*hEaOn+G>oG);8w>wzgt8%MNevnl-6&PY(FN%4 zC%d3c1kp<5SCDdu02cmB5co5vQPV8hTP_2B+7objbE(+?el< zM)%e3Q5f_pXlmG69-YlC>I(b(`N4i9=*|4Fi)Z?>dm^Si@C)<1&2)RZh(+~&Sl&3=KsSaPL#iml*EJo<*Z0}rfg z&PBKjNoka(cV5->9CCIDbDHvwBM&OV6Gw*-RMp?5f&Ru*kH@taFXSgzleU_D0N^Tf zYU;MDE0SI5yPUV7L2VD=ZURkLzn?c8PsCArQX+IHS#>`sojckpibR-%PApQ*KvUmN z-xn`uY_z<@m5-#1_^LGuBgRGuf{rQYqku8AUfWIW#>ZPp&0!=}4s@7Y;JIM@6e~;k zr8?>@{353?zz@Il>Zka&y*xU|i7N0{8vs?+!*@^kG=axBO_1irC6wvF0xV+Xt6^9i z$UJV&ZKMcYY=t_nOCRP6K`4XA^(b@&=}%B@{T0-DtJM_9cr}VRbe$^ZnWrXd%*~W< zIZ*q$8gd{nUBA}rTfm5~ukT0w7R0a_NVlPD-!0%4BgGNocUZWUbE1{V)}_VSp8%lK zp4B1C(^%y5`ou#*M}m+NsmC0s?(#S%0uvMd;P?hE<{X?hCmisp&?Qujy$9 zVmn)fQeL7`C#?@ZLVJ)FrDv; zn$_SR9bNkU^0ad6vtJm>u314Y4vIN$ea&%uql%*=y6Q~@U_q7cHq;Z96gutoINIaU z`pWBjJG9$#T8*@y01su`!SS;re{{?^GD=WgwMv58?cnk9ah`C^ zRGS{y8O*Pl0dVCFaI~$mgJm<&xQ3D4Oe$9NdO4?had|-;m?Xh^84l-<{=IU$`{XZ` zTTlo`!%jAarKdqWn8anqel_0z!~5-JU{W@vMX|Dm_| zXje_Jc*Xhar}f>cF#h zY&25@AJ#d9XrtCkMRqQ@n0bivFe=M*juAXQ1dwZ`FcxRz2IfZd9HincrQnU~VLC4XZ@ zgUZ>%wrnStTpNy*#JzqSGxB9xWO3BD8mP3Jz1uke<(%R=#m_MlSZ{6<33+d7D!F%f zs#u2G_>aFZcUvV%T}qg`d3MokEXN7yw>M-+j|6Uot=*d47zlEkWUn7xU_zKoZ%Z|Y z^>=58Mp{I|S8m$gNayAnAI52oy-p6fTXF zNCWK{N@&eitN`e=unyWSORMGU5Ut>-c9xmJa}u?!h8k6IF9ENo!XOizwjy_X$LhzO zSrcZe&^-9X>m~rJl0(P}>MXXGNGFatc(?lXd7|R^jowA9AUok}zMRTR#nLL^yRYr7 zVs9~xltT3yI6!1~HA%#^;@aW2U?sME7%tcJ)aVf`Jt*N`7h)0RrYPu}bAhqv0{n%! zsif(SOTVqZqX!+?8*ci{q9;A&S?ywO$vtQ!oji}tbB#_3>a@hi@L)4m@@DxUmPb)H zJZ{(OA6?A8q}p<>ojhVH;OW}yT&y{s0jNC@lBa(yYns?bb&v5vKm`%1;5er}y~#QYvILGZJCx)2vJBdWN^ z@b05qo@c>obVo4(L>=jAD!f1ZGrYT*k6!c#U`t6D!m^OVx+<@FqaY)z`7L9^s<-my zzLltu31yPl1ij_QL~TgXZm!?WoHG!_VzGRZkR8aF1t3~gBCCvUay$zW*yvy{bl+b2 zej9Qj7cmbmot*2RK}+hp;B*wVgM#)`BGA!Ju={1q+09EKE)!K`_P&f>8^D+iekkeR z!?K3IL4EWR&MxWkmaCG6?R)s>dTr9px5zV-S$4B43ZwmrBtmI-`NxOt_USui&H>P3 z9bd<>G8Mt{rlXv_XHsNxf?@+2tJb^}%mKqMASxxnoyE*&P=VGGQNob9JD6SCI2ySF z$WJLD?F=>nwJWMFZEBlX@D^m+duE;y>3bnw(gAAus zXNr@8-{@qpBL|44I&CvjU^4Tg*wf;sV~F$RfPce#@V$O^cRs1C9<34>4?1$9i}zJa zph;&`Pb!4Cm&~T_%(p}{_@FWCdnS=|)2ZF=uGa9wD@)AMlL_Y5hKJnJ>HD^{QV^$$ zLq?DrwJgxXU2=C=1za0xv@Jk(w8vN#;_rs3;Ht&Kd}Hf_h}9stIX+!!)h^diA>f9) z8gwQjKG7UOQ?e>>1Sz`JkvWH|8q3#8FIVYQUa1l+%Ca9gB~K6HPzH~frk zktNfM>#%9*cF}nkz1#!}76BGSRtq>x#O}BMKHaJYEZ~ZNCesRyo0bvtjOi*PYyxzo zJ8yHEhk*pH+zl2z3u`e>8!|47_dADPbWBXwQE(05HDlN2yGgufHwoHY8t&5rZr1rM z4q4{yeKMDiOJl`yT=`nY*3S;hq|>{JqTh5^9?`c+&Bjzg!vw3GN1*y1gGuS0gJ>cg zf<D_-m@}(HNw@xF%4B#wHkE$%qWFfT9NaOT9NH9nGi?jVYoRplhLjD@Ql9gcg0t72ey zSzT5Q$-YAs^4TvBaR-FqFWeun<#&(Uc{EQW?C-Hg1Nh1*M3k226kY)%MsQno>^Fhd z&C-+#)FC--ZU|F|OiWHKAdaE9mCY4|HfR`!VUnD;e-kUJ=xjo zULC96aNfFAQBh<~igL>x-*R;K(3kAi#1zuksqnFhx4(obNLA#-M zkjm)3%IQvf*bRGdA>KV*u>0ZDvnq)+b4^+k_zK>+Da7UZSll*;9f(hk)-RMjQ)@To z`Z+D&b|5~XG7rF}-mlNOkZ;4uRK|z$|r?ZJ(Ua!$Jfo?94}#v4m*v9X6SnBjp>T$VTt|np-qTP46cggOs{< zqT{q6XMW=QR8v4M%3+m`V! zYfbK&Ea|F>BXQADNNm7TmqmX?#~8J4#c88De(UvCi4BfCWS8Sm zBT$R_8K+r^m8>uI{avHi`YmY`!gnh)D+aK$DP-QNW5(JEp%LcvZ=$;?JejHZ=Y;4F zy{|@E1Zhm__^6=0ee)I92#cBiJ{o2at4%ri=L6?4#V&WA^Jm5npicfLZbc;ER=7EB z0B!|c%LKXy1c0SP0>aAcGBqtNdUlhpYvUg|+szcV0pzFc{zb9~-$~I_zV? zTQo{!_qfZa&<$xetW@5}SCco83z|>mPN<}_;Ru^mm}!;heOT0$q#_2AwN+WZ3gm<$Q+EZr8vDES_Hz*9Q(7IoXl&aET*O2fR}0P<$}c8)qJ= z9P%D597R=n$Ncu!Cq4ixzPtWv*sjA!v>tb5@rvqrC6ntM@1pA(G>z5mCGEtfae2YX z4HU5&`YP^5>m)3OlEPBwR^)xiD+NhQj+0oci7SLe(S5(IH5wz?$TaPUQ*6@ z-AyuY2Txg3ymHlAcLc%p(>twY4*?}1&S?{JABnSwXlyeHqwAcg;?OiY2;gUqR60z# z2ks5;#48nCLltE!7?S7_+*=lkbLn%xz&)^05Yz_nJ12~ujQHk^2Gfy!f;G2&z@VzI z>QmIu0C0sM)3MmkxrZPN5X#=gQ(w^Nb-35Mzgo+Zv#oXkBL`c-R7;m~chQ;<#!$3U z{kb6dZ{l<79GC)Xe;3zzEmDd0-5u|-6NrM5-W0Kg$sAh5D@ZbnA6kSx&kgzu&DgM9 zq!Q82Ca{$CdOmm$i=|)ttBLS_OuYBeZV(EzI+m+fdwq%hQre@hAwrogc;_zib9t>S z_;Xk|zPb0aDc_%1qb~Y@yt+F7{t~-9sMU0|V?O$CR`c^wAQKQfbr~@6dI}mr-vi#c znEQYDY+`a)_jMJl-LM?tNB`hwsrDDP>FPc3Hd^fKG7&MmT2tli)K?0X1! zQZPd1!GFKTZ{Gc{V;Ex=nN}+^37J0SrT+hZ|3AN8fC@Z`OC7H8pCA1%|5b(!di*c#5}HlI5m&aaS;iOIA5M*JlV z|2xpHLuIGP1%yV1U;B{AB`Kn2t#AfmLJ|>|@K<>=9A**EnDF>S?F90Uzkc$kgYXMn z_1{0^NCC@Ef|sQGuZ8RY`2(oRZ9e`T0y`O&rT1(wFXFj8k>l8sb1FTU4 z>#qw@mwq-`p(XuMVq$&9{J>^;q3ZwUusDC0nEI&&@RwukgMs0pX09K*PxD7J{m)_i z#q6UO%^&-Vf%%kE?$0)AfBqui{m0tz*-Lfj$>9R9{r|kZ{{AVk;w=c?c4z)S8jH)< zKhR={637qz`Ir8hxQ5#z-FddR3NHQAl>Y5qe*QNi^*|k`9W6x;!U=lsR~ z4_;Rs$b;Zacj*25N2jg=5eHHUM&EyYrGNV1%RMk&%bO-!|NhaduYnDk7I}*Izu9Gf zc_$w~JTTsRo+843|0oZTR3pBK|Ms5@#?LkU`wMftL)*-zn3{k8DA-EV13V!b7=Jx* zf8Vlyc}?_}KRiK8z}@Rw`qw^z$gL~DfHnCv-1+BM`lmO+p#9&5?N;LJGmxe{~rDY2c^hH4OSgu*_JF znFs&h?vFZ`Gx{yWGOFMn&hV2P`|ayLyne5|?OqNh%a1{bxM4i?>?50uk0N(2{i`UI zVI_JXZhkyM|9T*|d>CIm4J4)qTAS(LUU6VG>`BjXti;M@-hW<8Du0eX?!Ux!p4ps% zEoOac9lrffHb(>l2>As*e}MN-U-*zC?;*HYgof)IIJgh);Bhm0qYYB3k%d&`t^!+tDH_S_g8fv4+f17pwv-r zUg0{et?k+LZwzwEZGt1BRfnWYE&9e1jep^Y{xpy}GEi8kq?9M6{_U&z15urlL_1Nx z%b|cBHf)YV%A){ef>?Y+>Hs?IX=A|k-YRG7;SzIomx8e|on1gVNCyfOj(KR2x5t<= zWbDeYBZpU(wh~Y)yTMJxDcpuZOjOfqS&MG8Y?z=J^*2jHpf^zOT`N7}^vu#a9P>BR z8d9XEvNOFRt}3i?7+dRSv2>SR+0hfyqkH~Y0=Eps0q2{p-W(tKFfwG&0O-!GaHr` zPkK~8Q2E6L=kKcrNTLW+b`Dn3->VDLp*1=MZ&x`YY5Fo`?Qun}oKI4!0}w^2vyJcVj1D&7`- zeFacrA5`VeHL!OJP|6Fez0@58i|Gnf6+kf>JSF5q(7nV!dwIo@g%kh|4V=5e!lsna z54c0U7*}EI$-340&0Kclx~hX856=?(X*|DdR6ZUMMdZw$68Wtol2rz-6{Kvb^DEE= zM&=6N!Y%jZNCtH@opxy#K>*a^!bz;kKQXs;bwv#qnMecjEGX%Lp?Ud0nsn}3@)wt? z4^?|X1U9})qxmR~5U-FJf@3qn^Jl#(7JVRTrW-U)M86%_3J5U<5?rUVemk%?Xl+-G z2a0;u!-eSr`%6XmmoS#7jXU1oW~rI6c&x6XLIutR9_K(k*lc$}tI58icc4>P;#t|) z+4eW?EQCpuCQ#m03X0ZdYo^k9_`}vjC0B3AI=QihBG&EzWF9zxzFv~N)Xgs4#H?&%T= zUq2dDwezYU^%ra@Z`a=CFTF8jBo7jZ`T8|IiNY&ssWb1SFP!L9{oN3jqcaNI^C6f1 zX2iaNo&W@Y(6()?P0I%fR@|?^h)5;9qc$Usd=;r=omU#Ab$wPrrMOW|Wk#VtN2SM2 zefD+A(}IA~gObOPVzK)QSHwQv$?OjggnhB-+0M(ia`{Xa%unxYoN?l?x~a67kxlm2_M_dufRBOLBXtT_aQU!= zrw=Aj)_4!q|HCY}qGy36qyKkTn27$FFm20#Lo|RLjY{vY2_#|{x2l+p$_iElvT8Vl zJhNj@*p@nc6rCLoTDZsy#D8~3KQF>q$aGW_$j152P4pagma1&z=00tbhY}zk zQxr5WEm>%OeC$)MlmEu<1|TBq`PlY(F*A*F1P_^tXQ<~VIPyYkFI@*8{msiX!TutT zT-s6M|NAumaYhhB!m5O|3jh|Bl$7ubntOYdGz*@JJtV>g7h0`|;(h;!=-oR`OAOGE zP73S5y9U4b41fAXb;Ia6E_^QAoV(MHxmqZ z2`?+_dwY_VyPnkBcC)4L-S&D>)it}EZFGP79lu`7Ch?EM;;y%JoWE0t`=VS2F)3Mw zq5!y?p2Blev7c-n92l@MncJgT2+QI;rm`fi-TCr|k618_PTz8m20nRoO7Q2esKNum=R-7&5UF=#DtJs%E7Kbtp5TOJsHrn!4;D?li<{t7Ot#gcW6KuV zGT;&fe&L!7jnTu?mF5gc&qSYY~SJ7`vO z#v63+v%!bnxNhn z{lkaj>OHyK16(1-mC==`=b>gt32_XjkmaCaIUd%ufIW^sz%_e>z1 z1bj3WYZqB7k9jp$!|}ety@;EMls~3l^;pX{tSXu< zzjD|xYxZ)+27z4IAzoFjtd?I?k_RR8!$V)E_{vF!B?Jq*e!UFdGnq4crXH{z4a-Z7tY=y?}Fj2RM92fS^+7ee8u?Oak=Vin&;G!~v zhsz3g@AQzBT1*1F!NtkP^D9GyXD_AsJhz?FTKg){x>GMe$3Pd}5zn|LpG3bx0+;BK z9SmiVZt5cJIU z<)&atnS<4YWTAj&&UM;pj!)D^M{L8Y<=R}{$FDr}zt@xp=-9RP%(svAIA<&B*oS{d zWRFp!9GyG@?;_WQ(xnAExz8bx)!h^cdeFs@pydS?c4XHzpQdXcl1f=iT$zED0oJK9 zKl;nD6|_uwt7$idy_>LeOVT5ONPh~^QI6QEOegCL>g2Kpla;iYxG`friiY$e{QDKLCKc-j?s#BV$`_)Y6%yyT@&ssA$L55)(Yp>o5Sm^YQtp= zEX5X71=d>o!n~-lZ&RJ$wMK_H>-B?1saw6SO5mQ^Xn?yXNm(#4gnt;N_CnRvRoRtb z6tX|`8{UsDoAVDGm9SvSbAxr@4obXgOLGh+1=l9nIn_IR=e#O*mq!iPoTVE^dnsvA zH<{;ALfS!sg;0lQwrRzd18O7Gi&jgu>Z6IhwVuMZCY6TjyH>l5$M(a!(Pw(=t6;BqKgPULl6Hw-NZIhDQgxN?KaP^zH5K;ezg4ExYsT zG+#AI*i#ckbQ3s7eEN$%zfA&QF%S2=64lWwd9%(N`H>xrkt!KhO~}=u+cidw+K>iy zJv@2_J{88@ecaX$%E7oyqr12X=1yjXEEr1qbvFy(_N(6-2I_^=$yFB9z4Tuh9t=)k zs3RMUw_Ye2Q>?mQ0M5xkQaS|5Jlk!N57uSuhGPbRc|Ox7E}Ov*wqeO{6+ zZR6Hjg{RUr#;_?7$@Nu)>)Dm(4(4!GPbZT$ZZZCuBF`l0vZZ{s5A_A5Wkv{aH4@{9 zM{m>VB1~bJ3i|V&M+=*7vhz+db`T=Lj72IDVM{(SbW^=E7-m@gjx{fjwquPeqitXd z9UEdrx&-^7R;JCx22~e$ruM9jVr>@o%<-YlNGH!P9`a5j5i@Gndme^q zM>A>D06uo{$cxeCC~D~_iAk7e9-BdiQF~M`fF@`HuTB+aHO{vaQi z!35te#Kq_p5ee+oTKgz({lZSh)4woDj^-CBkY~&SO2m z%%k>EqEl?mYpsp;ON8E2pt3B~mQI#(68zd8oyT9+W^~9Lby*DGNs0B(I8qdxjmyTM61ARly_HXRscaXra7=p+~t)OR-&uK}+6rK~Q+VoEEtfS+= zLOPze5m-XH;8t_KPAto zLq7VjJLGd-4e7*_An>V?p1|K7m$8l9Z-C-!rqbk-%h`19tkSQUm}FrLCie_NQoEW6 z4+9>N6Ue`7P_wt6#^_c37F`$#nSDH&*t<03H7AObs5E)^<&`(97x~rN3A7W#bGc%A zGexaApPIjt;$V`~dSHJ4qXO2srka*Y!u_}D910nUMLZERv5TD%s{ys)H5a#AgZbWt zq-s0A^-a>iLtA!7*Q8#s3=s4(JW;;raddU?qf2ZN9kF_tcIO|gvKPTM+IL%uloGhA z3S~bm&8R{&ClB-u{^B)3=o`B<#~XN)cOPDP!(!`btkbErh_A1U$kx`$h8CTk0gGm)udrKuOELX%F=K(KC%BA7AeiGF`hP?uu6egY?&DiQ(RfZ)Z=x0?YAlq%=cd`r&-!EnCgY4 zu2l5q6u)v2ARi_gqfGZQz!-d*t#Eujf+EaLzoJ}9XT2}cMAe7eCJ1f+Pd%HBSvgNx z{}$6qZ?G^eF0sV`dR)MlrzoU{*2AilAW1IFaD^=R=eQot1)nW z+X1m9?R|6%_!OJbb%kPm_>sN_!wg4z6mkXjfZC2ITerZvqSJn6WVkk}il!s{@vWO$ zw(Ydqvz@!`GrqQ|2G%WJO!sg-3JgyE39tQ&z>GJAX3 zT9qiFYFTCEs}ZgE``wRoN^z-6yWC}ToCR-=Obh|#|GNdMx|b$7jeJS@O^kEl_{^EG zu6L`i-G%U@+gxq3q0rr<7k3cBkHTy>vR}eiu8+^;uk@wKZg3&!=!IV#(ldD=f)>|3 z*Mv~SdrW! zW@{GEcqK64IKQ#ARMg!@ml^+*d4O+uATMsm1E!z^sYog4?n!+F90T2sI~lQ;`ccs> zvG*EuJ3A@7>Eyfhp3ODBEF}>>WLtE8>alu#nXeSDc5m2Z#xpm^2do` z%I~(Xy<8l+>Qj7;$FASBu;hCP@h8X5Z+JQo7|BcZyIJc>hu5!9=~hUc9VVJ0&Jcfh zML&7O<8A>ewE5wRn@F3=QwvM~JiU_4!p9;`<2?8GATL4h?<{E1)PBRBu(YCasEeH- z{^o^rMum)(+0sdA4{AGmq`8sA_Wh~Ob**jc*HLZCRY|y>8FAg(Rsyw98G0#?Fzrx= zaJll4QW{zGIu#`^oH)8aE|kop?SQ?l=oriQrc-Ad8ynZ_&f!wQUes$79|nQ6%tx+)3hn?Fus5YP5dUYa5x-vhoqyU1Im@_UksWYfOru)1s<+Hx6GuEpi%wBq;?-qvj{#%_N^*Z5p=dA zDS@5*Z`d~GCV{>n|veDSA{ZV8J7 zGWn+vi3&H|QOCZAi^8-O{&~iESx`DWUfJdyp_*^JbRBo`or9#$TGgsx^xuSVO};%V z#`c->q17V0ST&JqtwTiO-mxmv_N=V_q%}_sD4gEFdG*N8LK27)w%CoI#&ttYqOwLw-ClqrLLx zQuok)T|A}2APRqPGJ(LH-~2N$j-4vJz&JXrp^c;3Z;a!-?&*^GCGg}`_Qp4i2!i$_ z>mV1U*&PxSL+5=kO<@ES$DekPB;-M>*8|XMP3R)V1KpuS(7PcX$kq2|E7O`+WyITN zCt(}`q#v=zB|Rv2M90WivVwCM9QgP2ym6UghQAWKSChvadMlGuQ#hfE)$h+9t|rnY zGEn~sNj<2056EeM$ zNK_g<)2%eQ(6mUXk0PAP!P!0MrAU;~!vKHY`y7M1Z#5JdoOnyKLKDy3ZF97FwtXru z4A~Wm#kp>?(+Taud^e4Svq*d-@?t*Q`UPgaQ;6Fd4nGekqvh_p8xvHpilJ zgwm5rD=)R5rqmZ0>RiP(hxli!eSd}M=IPQNj@g-3w&^grs*|X(=sdr5>}II;_R=sV zp`J@JCmW=BIu!61<(UCPfORe~uID!I|(NQC5GqVQuD~z4?wQE=xUi*R+%zN+T7y>R|2*U_#)+&EfO9cFpO(1sxTw<5~ zh`#k^fnzXn0jiugko~DSDn~&dHD1COP!KP^=4m#b1aHZEHPz+xww=p z73R(gh5Qx!^l|~!eSP-@f{N+(;Wl|e>xi2348Hh`I1@hB%ITZ&aa^LLH%-t}D zsJyi|Um=Bh(lJPl&AoHu3r*PK- zm!nzqnL+OoY*coJnYYFCn{~#MNnNBl-Q|5uDS__QAO$k#`bszN`LFra-~N>X(dP6u zFE)48!R6F`Bf+P`0^u9kOq6!BLjo><(YMd9qIzdq!;L^QfdRW6ndTreBLJiZtic?G zHBh~qDXTrqGc+`O2{j%SNI;b;7N%mLZI0yQXp7#LXMsO_TSz`o1nW|<@HEG;n#$eb zCz$y?SK4>p?&e?&%B)=>qB05=y1n*p$m~EeBy?zRJi@=%yQ||_m31*2f+T@YcWS?X z&m=r*3_)01j9VODA-Eb|nm3}Q0Q(?sHDULbxCF(}Y9n^Mc8Q^)B&DLJHLrg#KvdL3 zi4|6WNITuF(=w+%l?T|Zj&OY2yuwRK=56J@`Zvh^`{Qd7IS@lYy&d>83q+iSkJfO} z8beu(k^2UDFMedteeRuRImrDQEmY2QF{BhqC?~2v6i#W7^0#&rG{_3yp$F%vagugI`H{yt7eHBTYq^(sBpQS zWBGm5`$_fNN5@`wVK^iW+e>ei6t&0^&vLaG?7Ae*Gb#(CVDn9wc4LA?cPK1Us1YP& zLS$1U#I5~t@uAx7=Zx$;A(D1ZP*yx|H`uf8r>=XWCe-Z-*U97}wOaFp;=;89L(Q_S zWw!SOLIT$EmUm7=3FF-C6C3}!JE?^-Nas#|DEXX{a%1EX8~fR8UeB*S7tuL0yo=l3 z$J^d^1DYn9M%iN&=44dtr>FlV=4q^VkI~ow%SI0`AtM{iFNN$>dINW*Ze{aHy#1d< zXg~KMI>-?0w9;nawmH0w(pSrC$D7 zbdccnIYYnJe^V1K@sLwo3#Y04V!v~ONVfb;r}xW@Cc9k6z{8vS>|5qb!jV?}+-~ob z1!4D7OR^Q8FT?hIXYFz~Lm8^{nem;X3d%g70@a6js91$O-k^CLvZO$qguM|0q)MQ* zuB_N;hM_5LFJpc_n5b4m8J!Dj3gDjg#{`;bGJvvqqhPH+TX{CR_Q2>N(P04|DdUft z;&bt{@#;MLe=>!_Za!uXt4&Sc0`pKabUF_~Ji+~s9s|zH`dj^j z2k-PN*{soOOZzKT-8#h?o6TC+KuzhSQ1{&LZ!mli(l*9^^;fL2H}fV z0=KN2ojE8KF_nNs_amx&E!>x#9w6*^B7FyxJ@DFp&hj5;vzcwGS$&bRW*CEyZ$*5F zZCO(TSLlO%)~)C^ZiM#n0*9%G>Su?A;8vCWYe@14kuNOipYY*Ul&j*dvu_~ZkgvNh z!nxAdQ{RQ!O|Z_3Kh6b=2)(i0Fp#zWoXFrY+Opd=%_hfaS*Ld2K_|zfaKYl%RAv) z0o6SeB#WQ$e^ihbXu+L%Xpks3fBl!A`71ZVfRgP)j#uhZaFFDj%bYMA%m&Qj0cFs@ ztu2<*90(}fR?|eq0J%rulm!qS{CQdyZ`~6KEUvuoX=-)c(ifKPl{!wb_x9sXkU)Rv z-7~}dAYw{Np)6H{Vxj_tZx=02lN_o0M}}@fZn#Bc7R6t?NtX^&Qhad%a;yt#%7(A@ zC+%A7B}%3iya_XVpHdGdQ7Q+)?ibpr;v>Jsu`GnUmrbxV9;LL+4Djin;|y*eQ?Jk9 z+?MuCxHh??{UagzP5>pF*-gQ2<|vO&acViwXi`Si!PWJdNVqIMl3M}6lxol@q&GvB z1j6XycQj;!GxuZfi>L!*9q*}k|7SuvHc9l?#TOSeSQWUfvY|(G-$b8+LpysT1K8+g zkc@jd;y9>F3(E2MWmR*Hwg%UHfwm##Q%`ZLz^{*gR>gWH>UOX@QOwcB?wdrdYUflg zAY@huB83*ho}xHSk8ucQUz>&vnfblk8yH`Uzz6P=Or$qiC6Ryb{-LW~tF3T&Xx^ju zw>gRP1dbL7*pPL)VW#h3#ItI|jN$sTdW@8newLX7`|T@@g?Cmb!_rIHlW5!KINyE_ zg3i6bjCi@+EpP?lKGcJ`mS+!q&)kU+?ZAU?zD=)jzMvd7*Np$*pOx$!XCg6;{&BV>Cr# z_6CtukJEeILGp=M@)*pqlGK6hTB|}{cR9pk0J5h;m+2}OStt@y0;@<6UWg9z31X|* zcbsa=+M9r(t@9>aU@hyo!x5QCE|h4<;ek#=4it5shI^ggl_y6gt(1X4^<|CtQ?o?m zrKWrqjmZFUw3r4EbQ5JR|LXgu5P`kf{GY%a!{Nr)>d(V}I(EC7X}^3`Q>T-3yYV^4 zA&y1LGB*KoS3u!6nrR75PU7S|nDE$;T^ucg#(V97r0pZzU7%|+tAD%~{g5QR1USxD zC^PvksbE=*dJA26r&;7~S%yAIH*{Z|!U+>u&Lm6sR|=9Y+AqkUp~ z&=XXUSO6=~-NG4c+_}9&EFXz~zQ2sVf?Z8Si3XM&&g&S_wE3N>FM*EaiWj|onGjXc zeh0@}>P*+5u?d4%i?M_38TTt{G`YmVIf%UjA)>)8tVMWoW(kaSqeb02%u;NWx;c(u zjTDbTRsUXawp#^R`y4DA><;Z5uGJdoi<=RE#fV^ra z*;p@JE(Z<6@@6&IH=CQnl1V`$(#lPw7*sHQkw)a$qEhVLw58eKPV2@0oL0ZVD#t3J zXIx6JWd+&cOv8?d-t@Pi@5W1fjTf(*_keCxXt(gO4!S58$88t2;wnkJEE_Fya-NX~oK+?|0h*O zTa`71D_`A+`u864(riD2j5|IXzOQppcO9Ct-8ik5T96Ybf9RYGfsT!O z2hGgnPz}_Vm0T1CZRsZItjg9XheG$c2mQHl_Tc*NQ5Vw0#IR!=rd~dSP^pM}LWbgR zPUeij1v5`4pHj|q+9OHU2bf6XH5q^NzNW~dLKiJlyFof;<{Ji^aBvrD%NuTnq6=!# zxs05}UZiCz%fW%uUo_AAh!cWhUQes*=L?s3O1zz>^Wh~qq?4{1dBGdE&h}vNK%b3l z1UzFcD0=sw;9>titKxOKDy53Fa^XUD5dW>J$wN6gzQr_!lpNM|5mekDG7^BC?$324 zFaY!pFxT*ahxFJl0Dk49;xB>i^Ti)o-JI@Gx|gD_q!u$o%=OezH}X=>%Q__k{>Yo= z?{Z_<8*hH%?2-$tbV_{LoDB_-(K@G2cz%hBQzuI=+4cB_QjlA*N{g=3lsQ^a`#vgi^~ ze&a0bmnqXzB#Ko-*gsMXz5U#sLf##9a8`68$DHiR{5P|+=!Qt3%^zU4_hke!Y8F0> z<+iqpY-AVpwh)lYJ>e{cV4VeZ-4LwTpICV$o^N28B&lEhSvs0~^p<%Io}O6Q7`d0R zh_V7@{8${gPoKE773b2snE~L>wl-6ElU7=fl`GoW+lx|`=sEO=ffPdK)wMx=Z%akc z|D-3@rg(trQ}bsH1HJYBd6=Zdti6!Xn+)QT2a_^M1J>RW#L~RWx`B8qlCsRfmR*p|6>eu;yt@CJ?Uo z(L=f~9~Pi`p6dQsbQ|A4eiSZg{;P1wHR@s6rvekY={3f80&(zb<{qB|=RJ=VcjRU= zh=23h92OLKx5w;fX@z$spTR(fk>vWJ8uv2L^L3OjjZQhE<@uR&xkmgZJ29O6oWts# z=XWX~djSPr^p|*0CQzkMQ3f`CBC~{t!jikW7t?Zs8q_EiIh6yO%q$4ZEu^P0n)MZL zuTQGtw{%@y{hmz6>BWEw^h`-?J2~WOUzG2zSa6bmq;(^!W`^eSm+M_95mF3l6&!K% zaRP^YCZy%!E=Ajz9x2mAdQ4vh-5OxN4d6-9Ir{AF-H zz+!E`_QHhR?oO0CEWpXWIC>|95fpF2soTB6Zv%_UrZSuv4$iMc!bX5$F~hG+vIp*$ zpXtcSP1tE}rH0SeOlMmHkyl*IvB|D=ywfa<)_S^@1St6%ok_yNDd)Cl!sYWFJ;{H8 zla=m&*z-3Rq0SJm0zM77BMa6AqxKKe50njf)qEiZ6qF#l@t!GhJ5zzpqWF-@i3lY- zy_3_F5vxBdoV@t$!cDGKCDZ;{AG?^fUB=e!S#?ep$F1*3q1v#Ee3P{GRX7lOb^DD{ zq5qG)w+xGdTib@kLd8PFAe9s(1O%i}q)R%6P*NDW8xaMOj-f+32PB3rl|~p4h7KiV zhL9MLp}sZN?Y_PDexCgv$M@@f|2Ym*YhCMFSDfd0F^|5i2-MiSY~J%|C(xSD^@9%Q>UNM#dfy>~H)U2FKK45H9yK#&z1Gt5> zp^HPsc=!gCZ{jM>a2jSH^wT0E4$YHx3m07jeSq(|Jo3_yPUB51T+Tus^CO^!AIX-c zuEItt3WwkIJ^uUxMBjVQkq_uEWk`lnDKP~roeb(dd6weNdAC|1X<;{?r8eX73=UZ^c$ z#XS<#IvY-zS<^)QrE@_t*@QbC47lK{Uq58)p0}@HWx3yKx05B%yri7|hGB@umz22* zar*`suLE@x^*R`XcNJbl zn;*l%aY3gmp*O{RBh$plC|2B7QKd?RXIbVo&0)aM60xK;SXVuB>6Lf+n`euSsUV-r zm~efbB>x*4=darYvh@P4b56bvlWJ1qICXoW9S*Lp7=LOn&5q7aF)vbdwj+=OnaYW7 zL0at1vU?X()qt$g_;XL{K*>0l!@wwO$3B`?G~3LxOp{mb=x0HBn3N4gF5QFe%WhjGo$jG2KH1KI!@Y~yj)#>MTxv4U(d`OR-gu@6Qe&ywi8%gNA?C) zR4>`?ts#9&K#acfY;bk*h+r-+nq0_{D+!dP$Y`q&qGOJ96=Y|aHrBD*7~=;CB(t$& z>FMRH`aO&)0|yfIEF)yvB4`=gi|Py&$5rj1L~*x=T4vPI%@<6??7`!b^u?RONgQA(FCXv z082v}`XAaW#rOWRPlE14{5+`>g6ps2K92d>pS1>eL_Y>~>V_`9Qw~ZfH42FgLRF~g z)iz0LPdX4ao!$1tEo2)wygqxCvuW-0(ZfKXZmYe_tgoOXJycj5kB@KJY_CRTmrmSi z0a3oRk`kEEb3r-C-P2kkZDoIN2M#JIJQ9slSuux_vQ}G1U4k!CjD%!R$>tM>a=gwEOgAAOPo(s}fN#lanZ;e9EoiBJ zzW-D{SUJUc9l`k}S&KN|k<76g$G3H_eOEO2W1iEaMP9VLkO@QOan+|#30g*cKeK5| znmfWQm8=TES;cKGTY4&(EQZiyZTOAi?9=q_7z@R6Y%Je;M~KF3dr@+phZGx&F)X4A%aN5BM=|6;>eC+Qc-O?Qy-k@Bj$syBiOe7z04Vl@T|9 z_&0DEJ4-FB1IW(TR~ioLDel-bj@TAq)tqLt60-+78fP zFPL>P_1eSeOIq;aXE=fS$nKdz{i*ri|wAUDuX(!U!eM~#Vc@9Bn z6|JbT+ofGM_)2BwB_F$H=eHuw>ZvP?g}{9U3KS!B&MdipoRdx^hNKJmb3|bHx$~e2 z{>c$?sESXaZQ&Hqt_)DYeW{vNWNBMm;<~@=cUs;PUf@EPyhCmH4 z_{_3;g9+^O66jrrfhj`)BsfFEt38V3vOqsEf)U(`YZk*?KtGY~?>TOg&aWJITGnFL zEyo^@3KXWy0^S}adS~hdZH6f_c?~bx^&nW&WDK;x=|N&~Hdy!p9xlbT&mnQy1p}{` z3F7L0-4Vg9k`jJ{laq4>UyZC?>$o}a$pcJTPklBBI{4bgj$K!d<2B0=+E!MDAcmy7 zo%U3%E$GtWpcCi4V}$_V(J85>vt?_tjAvvAdyrumYB<|gSXWR|ZNjs+Ww||1!SXmZp&>+s4_RqZlHr}4Ms z`GZR^N5X;5k37CJu_ls`b6vw8MJ$s$g+@F!{R2H`gFyuu+#vNPc1vN>1NOHa{BQ%T zvE8fO(CgeEvbrF)$6Iv?@*Z-Hhp%_^np=o-FU@Wz)g+rrxd z@lO76xYx+Dp`n~hAg+PF;oCjGSL#U4JwUdB#JjynH2yZ(cNG^KIsY?^G_N0U`~jKm zAB_8vn;0@GkkeP8o`53G^b8o55dkidduhQ^4}(6qb#V{2;T5=#5T3QTh`~7xY%TOj zg272QhrysTM-Pel^-A06rYn}^g%CZxgs+r)T3J?lPBUM17(g~lDZ?@9I$`YWat+EIvVm|lZ~j$<1)&)SXk1+N zvCo3=(HGo_?C1GyJu~V-CFBLXbn0!coDHk$$wKJ8lZ7zvOBap%-kmHopsSn%z@bNC zs5^z5lR4HFsJx?58!uNsebOt4^$!u?yL2vZ--9CqI;4-E`NneKf8;!rD#aoM8Y2p^nHzi==2(ZEwtk) zJAis{I{0I?^NJq6hLQ=G4+FT|J6zTig7`|m<6{Y3ul0mU%}zwum_wg@i7Ao_3In)> zPSCA_8=C-}q?1o6V^`FiD&_RU~9tyT2&sGsR%?ZkL(nvxt-w`_e*kq{*6Cy z?R?A=B%}Db18Eu4fqC|!pr+P1+ocJecFlvvuE?e<#AW5wytgE5SZ}ftQHI*;q=g^{ z$g#ogS6!$0x#rw@sUD-hhJ5DKQ6OX0ki#0eY$}_cBv>qEFABpi_LZKRh#BVtVxa z3l-6dmEnF~lXp^>b;DBipGo^TT2_FER?o0w$M#G_>@j&y&mR6;@*}0-rh$Lux5?_2 zusTx#1*6_6?B8?P;aNB!p_<7_4~bY@td`U}J?T%m9uRc@QBaS0(CIIrgaz?`4N#0% zISig{phj>0X>`NE~fsG5?+s-1$V#X0!QOLx7fg0VU9($$k7V)jrdnAPz~Dq;_x znw+>^$eD6f)xfL(f(p|q$ylNTUE2lSJqB%BfUfX>d6#_NuL>&X!oQK!rQV-oS-HG8+xuBHNiutSv zK2;v)S2u2yN_2-AYExSxtx$S7){9$t=(dF`KTtly4BtCoTi`Y#yQ*lTW>l-E=bT`Q04yb@mZD;GXttV za%H9U&MOlopu(or;8mvvBfY8K_H}ido{Osws0y8>61)K<%fp{OJzOdUf;MWI7l>1_ zy$Vkh`kL-p(N$0l?FBCmZ&o3Em&i5RUvb0)@TSjUipoBRu~bfhi1g+Z*>8wSQ^>c-_dG)13n@o?6|1i4 z5H`))4l-7#1>Keg@iS&^FrUZl@sK?c4uxsI97gTp-mxONtH&v{i7-Tydk1~s_yL+L zMJVg5q?x0ifep|mRkUYQn~r}BHh?|r#O*A=APLT08kT#$ zWFH5MpL4ZXRj4S(HN!FH{A9d@!hZxcMvUd9@!QY6cWd3;=u?aVFoZWUn%oyOgLj5a zQ*;gWL3yUG_F#WUeH))};sHa^alI<|RiB>N^QSc$UmGlVhT`NdNeyorG5vg%+X**d z*f$G>?V3*_nZ3UzJ`>d_xrX^`Yh+YOf&JNpzT!Ej4} zzFuPLF_$%$77jbgT&0FMUlIO6GbKS*kcXk1EO|)^{A+0tp@_>P-6+uFLEg8tFBHYxUb7#w83Rj)62px+KMc^kXfJXZOtuW`@6- zQ`=;}fuR0^8`4*)iF1d~3;@m(zA#?9@j+I-Mzho;IMH=3?gJdco4*K{MA>5wDrz+2 zN|KcH-aDg{O<#vutlWrt%;H^kxj0K_U$6lPle=s|(&Dax?*@fSNtu;*l-ee$`k>>$ z-MkzzmZnQs<+16(;UydhF*xji*KSkqzF?DkRE72pHvhp>3?pa*c05zzTIDz}*|`9b zuTt=rwCMtoQareV1K@XIL;MN=LP%UOYFTK7iNXOU$zI53#>vG42_8~1+SHo<&v0gf zl6t-{r?Rpq=%M@*e#;^lhhjNO961aM^@f1;3n}{E|MP&R{#Z=nZ;MIuKP)EbH_!-y z#kBlwG5P;mOc2IZ{fKi+v*o3&)QIKjs!)$lv>^37!FZn%;F7Y!nRE z&NrV(yR)@&PRPn*2(M3z+gh=PBZKNe7{kM|*@D!c^{x=x^gy(a^mZRuhP^TLVq$}R zR8!JpU>|dZMO~bMgzEF`F)i50S%V-3N7Uo0?aftglO>8ex#-h#d7s6WnyT0_jjR~K zoIBAy;tWC=V5nMPiCJK~8ijr}a!v;MuDkt%uB+S^q!d@&;upVqWqU+7NP9Zv0mzQ# z$B&;*5BAg+CuY>hn8TjPm}B#$%|yKhR%u*6_KQeG^U4Z6JP5{vW+eiD(yI=Gw@VS> zuhZ+RqKq6fmk2fEKiQ+0pwKH*X9%vw;@BR%wxC!=ns<5XQ;U_01l^aDTOP;4reB6#8iUHq8&(e<)Eg~-eL9!db;b+332AYU^8 z=#JB3=vEa#I^m_YiD2XhI^KKO)Ec$MpaJ}f3huU2i0BN|?PvhMdTOcQ#({gg<*;`3 zCgqKlhBe0Fjg$jZq4wAIMPZ-j_03qhB4ZCFWd~Fh!?=#UCmFINT%&vKlyp&!L&8E{ z!62XM3fUV(&V$|j!L~Qj8tsjQ%hDq+;B)rzDtJPQi3{gU_IRsQ%zL(yr5($XBAb*` z6&)t<2PE9_d0!)KcsHRz{pfR2ujsCMmf+ebMQU}ucpdVL+_<{tqNA9;F@Ge|zZZQb zPvjJ>3wt}b)n!2i7^+Y~6nzdPAle(JiRN#W6|tNue&x+$TXVkx++<38<@RYmqdw+8 zqP|*PmBIstt#7&Pl6g#S8MVfPapi?4Wb2wi=P0KK9z4Z!)PM`Mq;vyK*BKx~pRfx` zkoX?X16Ta4b$q!kF_8i)WU_Gy-xk|A{yKLPqJE&Fr%GEEUr{i2$!>db-gv*PSozaU zB2x176FOT%2a!Pq7WUj(Cr^!WR70LZO0FL6CI#{jYr~y^GyXB5@LjVlIt|pn~`nk85vtUJjgnCzRhr{orb$KcOw6)JtNy zpmhoMh|;ek(~~Xy4droZ1&L{Ik>AhxxwQJM`*vCK*ljVLND@W+qJS1u;Xdd3omiTl zSbXUwtK2?0&}+o6Ibwg? zvdnr=f>=1>Z~r$g>L2{sMj$ZU2iQIR%!p&3Q{yX3ZF^L{u@rtZWkPKKx?#!FuNN3(6GlKF_JuFStO_M?WD0zkQ-jB?wH; zp1XyTl?F8-6;2k4i+}&|W~`!i`CXqd04UT%1!lug6u&;jvp9kg2V|3E#Df(~rB?^9{Dzi-z+aif3#KOcw7*Q&V3Y1>x+ zYtgr}7i^B9y6$3gHPm$2G#+~fpG40#cWj;-+w11tTn?+d-gDxxbI|g@3FKRqzx~+T zutR&s^7P1cnkS+v;IbW6T@$pXISi@*X)Qc|Ths;S#y0o@8D9wb-;VG9_|WDRe)CT= ztNjxP{P#up@nG?6{pfb;VeE-*e>eqYUI(nrF=JaoEzvuH|wwV0hlt@NA zHsgcVM-4keern;?zv=3o&lbIPCCFahw5X*G-W|e@5c~B3|I4rRLFP#~q>ovLg5}>B z%10Igi8LE^!9F+-(V$?wmH+!ybCz39U(S#XCg=U@?bLnwV@wE*;rljtI2Fr(ea)V@ zor*uOFOVw#`mVn_l7F{e_rcXg_7{@+e{e^?y^AQxDVKyVRefu@U>+3Xn}{r!kM2F_T4fd#yw^s6w)lV`AUB+ceC+W#jK$@<2{Q7^a+Y%CpPGuj$;Lvg@A@2J zl3&hR;0n4F|7H);h#(1DiT*P z*5A$9@~BbF(%*j)brI&b`Kjwm$5?|xj1%Rk=8n-Xq}kuU>?=@QE#;QK@kdzhGjp;j zhB&%*Ua>|<1Z1Kg06Q2{sR59gpmB%Z`NhisFeYUHwR|k-CmP%M zOrTXpq0}OO#+$snog7(b$U4ZQqBj>Q>2**58!|80=}cg|R*c}eP4(~0_bgaCS(U$k z*F!+HMvdL&h!?O4mrcs;wZ0`{V`wU><~M+)DLGh;7~;~fC`d{Fcueoj-O_Iiiikag63kc{qht)9Y=kYqm_ad zDZEqg?PHo4ZPpb1+g|kg7Ql||KN0k5J^u#`#c>g!UmurWe6-F78`d&F#!(Pd;G+)5oi(O zCFpM(;Yq61j?nxd0O)+7|1l534#Qgw`QrF?UG1$cZYZCJNvlT9?Dmcx;-w%}#hA^C z+J^%1LbVnk+V#(8Pt*hC5H0gf+J8LXa|=WjBpXnm)qtOuKDFvnAS4K&fNLYr@RLqp zh_qcheas6EZfoza@2HIcENG5K<>>jGY*DLqimK&8{lLzpl5&rOu5-rN8ccz)VOCj& z9913GmFXsHMTfWT^!A5RZ#9Ez?4cjrq<{E+j;DG=AdJK}|9I-j8GPJwXcg3|qVWjw z#YbH|;*| z_^JS9`=k{Uj#=JE7|j}K3urgkMebU@v2)#@5Lb^IosMp|FAST5 z$7|uW=l(io|MD+7Hh}e*a{TcwLBXIM6)Mk--WOP}gPqAvJa(ys&wj40 zEu8jS|G1IL=d5l>)J>}@Is?-pL0r~FDwgsNwz_4Cg}rxF1DyZfM$TLYaJNr>i+`4V z(!ht4jb~0|YUsIU>bNarDpimJzUr7=C#w>5I*2&P*laqg-Wd(W9Z6sQ{55=UX0cOJ z+%xFjAFKLf%YFRt;l?eI@;~xTfUl>kkZ_jH*#I*HqrfyrNsEM}Bv!oE2FSaVx*CT~2)qp8CgyeOLti{ia(9?;qdh{PikSi+UJf{L<6Y z6T7nj_YOLe_kYyHE|Nw`xyG>@wAQbk8s1$Uc)|Hk+I8RGbdmIx_kf<_<}a$quWtfW z@&=B32&e4s&Wpr=A&F!=6e3==i(^%#5`4#if?cSn_;dYzhtYLqZ5?$(fA8e=l9{Eh zA|(ZafAe#IZXqc1Syo!-~lf>_JMg>RlrJ(x7TK;oVYZt zROwC;KYr4f2DAo?csxlQ&x!lLoDC4r4>Jo@oWovLdjU4>@oUj**Y=$cn3kzSFT~*3 zhbvwkrGLGsyBfqVwil;N;!*UfUiyq}WV1$T<)s*)vyhb1mQSu1bI!?wj+DUr!xY-l z-RS<{b-RTpM8;o~j?nXRF`6Msp{>;@4F@x1b^p4}yDZ99x96iO-SeSBA&$%9rGu79 zR0ZG8#m6h)Oj44_Fh3P_JN0=}C;`WSNa7j(Q$CH*kPu9dqE4ZNl;2=MeTzGcZAmM}&Cftaz-e)d zC~2fvVMS3wx9a)>Y9FmqljrK$fz`t11<(r7k{$LX;R)4I>b=rna$=k*`Cx*ntS6qX zGOTY_F8F5?NdVtO+Q%+C)Cfy?Yt7sY42RGPq3bq)P(z2BhAwIGIQ79-$*bJvQTPG6 zcuX>;SYV}ArCV@a?y8{6>u>iX9ouVfB!R2j=GzyPL3P{r_^cjNSIvyr&t$qI#>ql}m0CqH6*kW{uZ=oqb?Vpa(Y!IaYc>h5`%Oa*4Z9q) ziiS!R%XaJ^5(Y_Z< zOG8zY><;Fw{B|)0G^-N!L1+%ooVWBcKDvh7CwPcc;uuG&uCb%Rsn|3)uvm%b$naS*A3q-2{o zy@q2gbL$596QMVnAL{stQw%YI&Z4KKkhI?j; z1=40(mX?2DlXf;ds2kag0>gv?1p4S}I-EOAw^KU1SDe}v-IAEBU>R0h@)bBTuj(>W zAZ6AR<)njkT`60+%#Scknn($%wi5%Q$P#H%_k%4LFG;B%WRADSneU`~mz&YtJFw`h zTrbE41k&eRJ2$(cC4O=ve~9%h?aB)m9;laR8|kem3}Q}i#Kfhr!Bisf_KUdvO+4ZcPVJ2%u+VWGtfw1e9Q6op}Hc&dkhAEdj0)=oyD5dV3ik)~ibngAq%K`4~B# zWml&yE(FSP^dHK_pxfiMPnbzi(CVSycUzf+9;q8Lc1=9UZS?pF^Gyl+ta#c_MDqOJzOKOwU(m~#nh z(t3ryFrE35@km9V*0$RfZ`^^xp1N~ZxX4O10}PXpV#M_%!T{t_WZJ{Cd)&mOiXxmtIDBsnfVAm1#}0h0has8U&}o#-!UKBOLn1QRfxHOlKaC} zOH+DtboHqots>}*O8!JUxq?P136+%hNN0Z36>0SbU5F$usigE5$kAjP_V6y z`oY6MtLu+&th73vvAN%1JiP(Q!Z;oWnoo)`9Zc;YJ+@^B;)rq#3W<;5D^4}|Dd8U~ zto4B!oEcDWc37Fv#SayP6+tQ#KqsHN8uI-8wT};cj2zBd>mam}YfQuGP5zf6axHSZ z03Fd{-5h_G^g()=x?sVDnLPUPcm($aMKRh+zY98C&D<6*WCG-NO%jK`QoHJmp)NqW zgyNB=ba?o6zI%@-aZzx(ii&CEt3wq zwvW-VTL3W^-^80##MPs3!ZYw=D_F167KKm=Y2y<#taZ&2&sETDMNkME(v?_^mdg(m z>06VMw-|L_X%nQ{C`)ItL$z-v+!YeiSdFOG090rE8Q!z2?t9hFGX|_ z;u8BtHaE6W%tj1s!0x9F4Co1o7IoL6+g40o=8rLY!P>}%#ce95{7H1U_G@Hzhp#ff zaeTaiMcZ)lKV+tIl@sIuThbLw!mROJzeBw++Sk)vrqpmJ?i{y^jA#0J{%iHs%~)T` z{Mi6jq_ld1+(KV!1;A?DqmRGD$eN0{rg`Hz!L**yc;H^MGT99kq!xvYUDt+5hja5} z`-Jb#j3lK*TQ9su+{_|?bU|HTccc^u!a#(UhN4a+tZkF{DQ&S#rl)zyp4mGrT2jwD zKuJ0vdae3U61G?OhNTWc%?>;H)@SmAVGw$GtbZ{D@BtlPSIT1!0-$-Wq+NBSJM=F} zImdkVrJ*2~p{Omx!UI2Uf6Y?)Va0^*!K;)aF>~LIfljx^Qanq6S0%jp%bRo-EDB=u?+GW=Tsd*DKc2 zOV!@S;XX98df~UP!a&~il+niG_0hmnbj~R4_6IA}Etl6G^RBah?d`m%)$4fD-{?iAwb#RErr*I$hB#l&>FPTl`#g$o1D8KY= zm$hJ3J_%nsR~}j349{?t4ym4($^UQ(WW`3NU^)U0c;vv$dwUuWyreojXQ!BL+ZElD z)liLOcd{X#j`--Y&tkvKP=&^>V_q>svVgu`vRSxQer~HpbM;lN@;}JU*%puVQbPrm zN_LDE3PNut7DO2l2<)&&dgRF0yW>m~1drlxm)0k=kF^QLyF&qwZ8LiLA7qT}0Q7Y4 z_?@)L65ActzHR;^d&c1_+&ueMmNOw;^y%vZQpY_3y-iH~*s)_DYF+KuKWS$J{4Z>w zFS`>2Nwh%!D%BBO>c%~5XLc}Q0r|FPougmZv zsC1GstOEvcS3wA?%E6x&Jo=LK<_ri9U_hU6e1!U2x$a@R{XrN~8248DdbUHd`7ikz*nY~s*_|m*v=D9jn)K7945xhfq?dI8K@feQWr>?0g^P0mo)Q0)|rJ+?#;ND zo+ZU-89oqV7J{HH7}HgH{fVgjw=FK>LWXul!+$W~QSkaQ!->!?9>oS@+y(^gl=Q|T z9gvJXX9n=eK7J@`=Q7aYB%!^FC>+J3yhZjF6peunCy*rP8%Zk;4!=@u*m_p0$}SVn znlK1@F;ZneU+rYtIW577#zXNxU*oZs7+2t%y=Y%NU{+x@-Za1dJVLvRG}sgGm;so@ z;1Y*;qtaogV2{_^)9kYg!$e(z;bFaB7hk(Q_WoHQ_j^`YC;g2Bx2gN$tqiTA24Qcm4v?mRsJ)L*v2Smc_?3*)%gc)-5Ed$X* zXf+WhrAw#V3dtFzykRy8@5#YM@8KALA;BE5h{uUfwPU4v$fJO0L3PZi7yBx#tqWcR zyFN}Bz}pEOkD<_JR$THD-k@ypn6R7P_B2*jnu;8Isk42sIDYbp3aYAcl|536I82;C z>HPiYr>u^NKfpXygu>NENAfB^9)C$QA_>VQdX;uV``Fk^xOUk~()=NfluMQ={kpH7 zNR1!jy%=tM+{AAQJ{*eoi0w=#BOCZ^GAR&apjvB7lgX*uC@vYwV{0z0oA7W)U3nV9P+n- zJ{Y(Lv_r&s`$VRJAi+u-5R6amw$i*zfIMN8W~Zs|U7;r|$z0BT+d*WF(7!#DU5Jm> z|E~YpFqrkeWVu(qo282H#7g{@NF<4uo2vFsv8yq&qGh*mG4G|%9Oye*5G^*!3C=SQ z$cmIiipX=&#|z&KV#q7!=pTQ~BQGE5u2-DNQY9;Y*`MP+q@fWS`KGUQ^fl_fc&)@+ zp-ne0%Qnmy?3}FY-RCo~qjZUvBdTAc4Y}WWlYTmNmH3XF7oSbq%;np=Y42L%t!MMj zc{3R!j4y;#hQe2fQuD$b@-R21&vxrftB+0v*U?zsK=SL6Pi0W-9AKZHnH_4`QL%V0 zS96RLRjIbZtu;LmJtZS4(>J$(u6o}Xf!Bz^NdX61$k$H=6VdMHgH$30ODuo zvCBHw0O32hFkzEGW$fB3vaHXBWln8KWGIh`<&xJB6+yz$4XpFl+g$irzF6w0g#A0Y zsGUcIpnCO$_=-oTs#Ydh+-5Sj#@?8V=-v(2-Mbocs=3LUfvWFN+6b99YRf4Wx6VLl znRqPV17{$NA+YP{uaGZMLj=EME zC4ZX1lzbxsW`eJbgetn@xEM!dpA2t)@}~~ru>fV1UQj$2 z=QQuXf!Ch|JtV&Bf`S4$P&j4)#HiZ|91@3oD2QLp`%*~X_fzmqCg42UZskG$us&7m zLZ2`6n%=WKA80L=j*8__UP8lyHT?n=gf|CFah9`Apn{P5->aqZdS8^Xj;on%&=9JK zmesROKDst-Qe?}a2(9N=rWd)%C&or~N8<1szdiQxP3x-t$OKharPkomRw>>4G-{6) zRBHl*1ZE=cK+7z`EmvDq*6dwFf(Mbd$|2-#pRqd_B9WNsAq+}x^iokkg6&?+*3QNP zZSFo6RC!xMsaJ4mbrb4?&zDO&+2o}l5bAvAAw9>Ejr+ZHNi2^E3DE4L1W97$nqa8x zrM}|S&|?-{x=Q3y zn-uPI9^-DXZ5VMbD>}-2oqkhK= zpGSBPJ;+U7f0FURFn>Qj)M^OV)nv=*g6nswu`V@kB2O8?Y-6E%-W5~lw4h^T5n&rA zoMUQ^zYnvjak4)pVVR*`xcwz2Z*TyieE!9O;Z=p{f$ESr%Q17U+OuxyCmW*YB_6%h zpDtUfwoKIES{dAp|N4F?`i^DrU{lu}As-_4+6R}|bUs^TG|U`qH5};T-LPp~a+|7W z!Gwl8s$E&D2zzw|@&wnp*?p*0Q4%bwLz(6v1Hptw6S8~|b5mY*W>BiKRS(JT>Nwx` z-c_iG;VfhgDw|k73v-FdL6#q$+84S9l8DeA+7xH^ZTsWsPO^@K3 zc>+(~-v}0^As@e8sJ-W~?U&!u5eCVo*M`f-kXU;xzi3^@wAM;A#Kol~ zB}1TZQFgP1G3`t{$&0v`YbxZI+Q!)TuZg>guM)k~M&GuAciDiSqXHLSWjLyS?rX7N zYv5q0?TFKOOJ}~;T1Lj($ z`qlTKCppdXGAH?cG>g{MdoG`!4VW@Sqfg$a++{7bhFgO|aES}M&rvZBZ`BYq$O9q% zf%Sj^)K2eC-wtXAnd##)JwF7j6{1IrLo2V4a_(u6=Y}6KdKI+bos5Hj^1Eqo*d?BhM6*UIwTDQObYO)X_YG7Ck$Ge?;BUsA1eVK6TvJNsE89~Z2! z%j@ALP**n*I*~GA&33klT*O-sS=6v*UU<**Slq%u=#kVHI=%LZ4w#WHN3-tzMPV(C zDuuNpUEH>Vt%JUNp}4B|yCP00Ce_&Kv0&b+_=XPqDVIIcY^G9vJ+5&a$84n@SB$>? z*L(`bdc7{%@@D9i35EW{@oGoBBBS(;i+1XF7BV7@T7s^2d(;LD;G+U%Msmey;~$-% zk7@*?dZr}SyYXNu6fz!z{LPLywhVQByVe!^?0USgy>nd0Jb5|$;MDkIYp=gKa>p^O=)U zrZ%rxCoV2{s3b==VG@8<*>Wu1w?j*~g*qVA|^w{p2^?m>Txmpo2j2&enYY8{1 z{bqp&qxtT^j{5|%*J}cOt_7AJ{m6yY3PflDHfY@MJ3RB(rt?K*Tg+4wu(; zGwA8YgpGX6#A%U)|LZNB^`4h%eYa1OZgkzFJIwM^`G|K5S%t~eGXQx>90zj|@AP%a zU%Y%-;9OrND)r&pBZn($jbs(yWxHM@Pox3+6Glm}7hF#2^TZ)#J?vusS@L(%rJF+j3os1A`ymr-)3Z zp2*ocw?5Yu34lfdoh3qdlPt=g5C6pPm&JT{^I7+<-%VXN*ef{M{I4feWv(lBo|?AT zZ#veXZQj`ObMkYs=9Q2eM1(TNG1b|0T+i;I=S5YnfWl@H0?0{x`t1zPJZ<#p%a-a= z@|UeQAIj4gW8CS(EMT!tdK51zwkh1X8N#H|( zPO$@AjGAa;cR&7N3!+l*A8qQ#ir;J#NX=#^ zUApSR)C#ac%~iBksn!&DqKkMP8owsBgmF zB&slDvT8zxo!?h|<)66i;h~hQ@?!8Z2!%;ZMlNs5U(tPc54=!rt-xV^bO!$A$pd9F?R3whN4`#=GOITds_^JO&=S6S)^dgb^{#s;&c*YH8mL5 z_}KkLHvqAM+UKub`PqT*F**DQ_13a=aVNtBy`)@McaJ9T5p)qV|E$kksIGoO!MbSj zko%)+dfsz`mt9ep6RL4(=|h3itT#?x>ZDCMP|_Q(y|YQomxH`(XS}sq*usDa*S?y# zMOpQ*ar?q3+QV#^({;C#F++1Hf8nl9jbm4TN+`}dlEfY!y)WnBeW^LYFO0pz{?sat zMxn#@t=tYx!%1LJjei-G4)E{Q*YT5SDg3}u>#TKM@89|q;eBYvA}aMH+K3BeK0ln) zwd|w6(uB*ff3>P=x0-h9l!JK4-O=Ff#MGsNQjd&8%Q0>BEHA3t&#ybx0ddUi*T?dI z!5fB2U)0+sIX3jm)rjRespcQgLkB0i5hS5g^z^N>D<(N)d2NF0aox+(6$UHctcszC zgZl)rBXP_Af^0s&4y}rCEJLOv$BIaQO$HHRaJb>AdPcQRd7pXGylzds)SJ$P3|e)g zl*tQWqr&mmNmE}wmKR^FkCd-5=SdVYdHA;6MTKr%-c{j3ku~t(tzBi-YvjDue$RiI z($e%d2VS80>6XLNh#JTNZWIU0B@vE3q}i-2c7%6P@;eEkjS?cK0MhUqrsDCrU-r|5 zFqHMO4CpJb9l69l8@pp`pK@${yQuK1^*bMM=*|n&_;=*C!0X(%oYHgwr~TQxt}Qin zU0qf{XLBgW#|B(oKQGp6JyeHrDB0O=KR7DSCvUkJLGKG}M}M*ryPvr92IjICr=PH< z9jkF|#S%i_us35hn5q4t_6?cRUX4!(x=YHF zUn!KsoB61I7`c(kj~bV;-`{Fn@^RKy@8=u37Rr_kdAz!N%HPHbXe)4A34MHWB(cpL z3Y`V(Ycn@359Z#K*I&*|ItOH!=qAirenA~a?!Vd(#?)bj%GGnJAZkZYvFy*Qvapca zdnmDdDn@NdYyHek6}X!XJkim*o7;vSe~`Rg)igBI0xjm(rfLmbzm`hQqT~a0w_f_< zC~jyh3hTYh4>UHIJgMBDno5jmK?mpET@<=-`e@{G!|=2uwF6~2jH|qPR50eC!+zIg z?=s_T;j?|7pIQKSc>4A`tt}kR^!;WgAmwTYWLS(rEQg_AqRUi3p|PcqSds-K&|dI| zWwb?qyRZgRu%&aj*Z=BSJWe;yH^_@{LK~1Z+lg<+0_%jkfoXtIdrq$Pn<*R!>_p~e6R`RsEZ2B{VU2IcO0Y~3g)qEF1}uGincVk zEKL-^%1nHn6a^EdJ>xX?Ce#=iaFAPWV;hRRTtz1b+oBHSB0r3L@RL=lgYbKQtl})) zI?b0>v{Tnoz-@1&JDVL*wBI~xx@H`nG>@{W43ZnZWX<)so&{+;g*65hQ^vmf_eCVS z@1FgP8!dNS@Ub>f0Fni<_6>CrvK+kDiJdt0)0xMls5h~~o+APb{e}%c*5N@`cJvr2$lR4W^sZ+nRHJ@%M zWKCAdqo==;{fXSN+6UvAN2pP!zH{cAr{XCRV9&!HFGN?Hd4w+|vY)=#(P5cCQ$amB zU0uoVjAlvqPo{ly*b_EzPF6OieOh1edUfmI{Tw1JSkdE>{PMRMpix@S{qX?rLDlrObFSphHKRQ(lzn8U#MDrqp{%}^sy0h6*Ck1s}e01&9% z+mnoU*5i_M^71b1k?7)LK{?uVV+9oZB0vX(Ye{TD?VrWZ{?C({mu#aVUKJYUKi zr?`zL&b~T>)Z;Zu5^{>#T`#Vg#U8Uy_f8lDT?5IKh)pd)&mFb3Mcv56Jr8UE7S}S@ z{ij51VW1>Ae0|6;R48p70Jxo_jqPZXaGIWDn+1_cJeJzGH&`^3Od|&KJiGL(Q-@uU zWFz^*t*+m>!an8azpU>}yLbUx#A!uBe^i=K0QbLi>QAP|G<~ zsWmr+mp$e!@1$DrESkJ5wpGUv8w<*c>SuI_Mk;-7uI3%3yHcB|-!PATlWCtRs99fX z3w?TYS*L(Yholg;)v4aT;GWFTd>6$9O@Fi>;~h;n*sWGqeu>+Su5S2++s$%vZ5X6#(jQo3N-+OUwe~{0b^l-!eDi(*{)aovb3~xKq*Ua6Nn6FqEr+DT1*G3 zz?;tkz&B565bFi78E)+pb;v`*YuNdnAx0WS_4_;3vx-vu%^;B|K5krS)U+I6==&oj;^@DSx^W7muRdU!NepWW+BBj=4 zi;vZ+r~2LR?a4P(`sNc3zU9GyI7dzS!f9M^zQ#IKOi$NZ&k?gqCwA+66uYwry<;AB zVO1!^9$r`MmaenClAl47LDqSEO(!%{faD~K*J>%Ms|9|ki5z1k<~p!Caz5K~5V+L( z`5jIFAv1OnBOCoOP3*ja^de34h--xE^XI;s_Na$O2@9t{!eSD?`+Z-!lSl;z8!*h!^GxB`y- z_k)-9Y#`LW&^BKfj`yNBE=GV6R;+H(#Hh|;PRj#NYEdc~MsU|bjO zEAR*~04L`=qv|L&W?jE6p&+uikGt6btquJHj9S268KX1)Mt@eSvQ6>SqY7SJVyb1R1 zHQeL2fX6$zzZ5D*`@yF#@K|sg)Ty2;Oi{Pe5UOOeEGHan>por>4hqInwvPtfL5wjs znKLLs&gRbEP(Fk8ai)%1+db8OQ#n}4H^APkP)w*B*%>nn(P(>JD3&?N<}Pqf{@^2z ztLyYl<)IEeNV-73P=$IvC?z|Gcb=Ai$rbxRQel_oWU^bkS|p#)IrU8IEGYv?6(!d=0#_deTm?)HAa@4pbT z;LWUAGqYx%c?MT#70d&EcL_)P?Ot~dyyIiSOTkbf*j)CrSTQwOCEZahT36i^znXZ`s#v zeDclCYL9})TJbT15J`E~RQ?wFmJ~x3S?Q$Hb5DO-N=|OUtC99f7 z(L^{Qz-lnY3PNqeZ#|9xcCob?Jr@r}m#n^7Bg{J+jhr-t$iQw7gw2&~3Di?7xUH|U zJy|?9AOnWN=`BRS4`s?E zoYbZ%{n~0QmvR`={thm!c={9EK zB+R^)s%8)53MACRN;r&WpiyTJ2N=|LB-!?*(_DS;V%{E%c1aD8O1yDJClUUN#>E8g zXyot+TqP{E>T=m^a4||jA!|=HcW+;97AwM3oWcaXZ1;<_{D2L-CHa(7;(ZAXI$4tr zu22XrP-z*#%&Y?Z(jy(Tvd2>P64j67M7*R?a`^p%hQo5&^HT14g*T#t(#VWW$#uR; z;P>Ziqe1-rfMRiT*~47f2m;ry2DQon6Qul#bullB z_}UaiH}2(wDilZAc8>7+;Pa*J<>q>@pY*#xokml{c1$phIi<2|udM;qX>kx27?qmB z2f-dNO$PNrdn6*eoH$kj+}eV4D!9QcJo=l)>ql*CQt662wE3qsK{Or>pWe@-teP#i z_vv6J*@&h-*DCfW)F8niCHFpG?Z#XoBt1E~^+S}U6DJR9XI@(dS%#0QPZ-F;o>TKb z)c4#BstR3kTXFUmEPHjTBKmc!&KrK7A(zEV#%tS};n*{-7cZw@NV{h*_lnTUR;9eo zLJTl-RF`_l=HC=a#rEcJI;3U5Lot5oU!)#y8DbSD;+rL5VBM);h^!{2A>Rq_-u!Ya zhs|b=bt7~{g+)Fk8Hya-sBWyBPCZd(X}`=##bDhk$0q>&P~?$^@{G_4$5gL%fYOU{ zbGu;Ic{Qf*eefUE_Sg5*X(`V?uHyoQa=EHDNxsV_Iq&VVmskkf03OW)1=^P=k0ESNCY@v?SWFZfFxx9;*BIiBUxk`BFG!kKpEED5Z z?0T!GHJrzW%&(LY;Jx4&Tu4_eq7?a|pVM2368Aj-oC9^WD#V;}Q()on@RJMN#;=7J zD=30MPlBZV*v;pCB;1x3&V=K~0u0b4 zhid9}wI*kt?nts2e2kZrj=1D1Sl_|!sY6(Eo{uH?OcwBjd`Jy{Uuw8zrCwoGsESpNk zS;CjrEKQa{dDKrH^L?}qEITVT_da%&OXg*0gvefW# z(6#iMnD?IMdW-~~K`UabZ?#+ULD_~9Z-&n7jPXu2i$Q1Ygp@dbMjN8c7To6)Khvp; z6ZTj=Sr!tvv+4*mTaPH==OL2|f$b!sm6IGp zI5bdnto`}4mQ12}Nw}ZILmKyy)S#THrQ>5?ge=3Jef|u%ux9>n>O1*v=dE7PQaVl0 z+}pAM%tBW{x()nBpL0>Iso-7lXBW&n(>b2>W$|Dbt|26G*txRU>WE9 ztMbYpnX83&7X<6HPfi8)EJO8OjOx0Na36W7G4SY3fHJpbV`YZ5JQ2;(2dW`rOuC+> zV!V*-zb6{q2xgg^;ekCL`oGr0xE|__vm0?+LR}L@9A~nt>xd1UJ!q?7%Pr7%C7=x;OaRtvs}l5JiAlvwi6b5v6-k`}a|yW)Q6 z;tga|8APpYwXEs356s1z)~5TsQJjDH(Juuk155KUj{Q3Z=lVWEE%Lml%Rr?Le^Oqq zy!xvdCpN3SW)^^=Hu7?`kM)}y4{8o%@gz{^>n2j?%LjX8S7pFzZ!H2OSpFDZsMuXn zbYQzMgMBx+NSGvjO|AVSPakh)WI@*Fbdpqd@|~@zOJZ-NeRuDmP>uB!aXMRBKTN}C zS%LA5>d+S*LCzPiepN%#XhpN+qm{ktHhY_d0=4Xf#9}T2U3~=ivX~F{$HL}=8}Vj; zORv}@m%g^jyoh7V)w7yv-@~9mq<7v`AuNOQCSC>v5TT|^6%-2mJ*6At(Y9@hlJ{M$ z5pZ|_I~~9Eqr7;t+lM@FbPCW@#GNIIvQ_P&I%_fh0zJ!a;g_zi33vp+PLqYa$Yqk@ z&+u4=oGglf^qHC6)Z6vrziUQn+}lkpl8+A&FQ@55q#wq5%Dfq!oymsA;Ii?_8GodE zCfr#Y)J$}-W>X3rGF4d%?y~GOCAmz@?j>VzhZ3vt0&1nbdAj`^ItUkM$VqJ|U(K6X zHti3sE}}A?>5A|_R6nTUzcOl{3x}<4W;Y0rJ22OAD3Lw&03u{F-qXfd<+^N7J-tqq zAd4cgDfJ7djs3xKXHzsQwg8Xk&_R22uOc75b6GWN z1|!Db8OmY^4M;g>wj-1^WScNnS5SwV=0${9)t9MOYM~6<2ktAEq&>KP+|#A3D5c|} z`e&ifoLR>2wLKT0OYrh*(vLmj3o$vIpr#r4Uj!!w0g7i|+3ny?jm}5#N$#a@frbAD zeN6KDM_RbK4WKY`x17;bd*;y{dhm*=HOG_8t0V>n27tZoG;vT=w7Dqg5(5yI2O(pu zSz3eP5u#`s`sXbWRr3&m5rPaD(D&sjvO3lkMe8}oBNv|g-hc!PYeO5*H3gX^lyob_l`Ii+HFIyl4F@d=AJ=tTyf3gZ z8ltnszr9dC2BsfU^|`VfAjt;qII!J#XQf((pfIlE>1`(II_H_C?XsrFcz$%#?o-|q zpDG06qdsU7|Bn_>>!S}f=7(zvFHob$wIA?b{>KLv3ip90Ae|^QiZl!S2vAV&0wb@u zw2R*fIkKPB(z((AD$L$HJ{MUAE;zq6n@G_SdG3Q?Kl9%iAO76gc!3YANi!@!xu&f0mZMCzrwJ3OU3_I(nPW82vX^rC+T1 zwpyJ*d_>JmN$&lhf9&7A5}zaHH`eSbF8nqvPsfoj1?^EP6xY93R{rb5{pT-UZ-Jd} z+@ZDc`FGFw1Gxk|Ee}|UVrnOS`R9B8?$u~12u$q6Bx8P?XX#NOSc#D4@&0WA{eRic z(|)O+qKuE8^`<2+7)xrln>6P?N2)|oKu9c2L)83}d%;Vb+*_Rfw9fMzIL3#wD+^P0 z5qz$r->SyKzfz~yao~hla=3tCro_1ola^n)Onf%iNY_{W+3 zk2C&{AH5xj{zquo&iJ>N?ni???7P(P6PWX_6)*1tSlM$1cK7$0Yzht%!{|q+h<^D; z73^QVdVdkD><(I|CEme*Z|O%iUaIxS-On=U zzkX(8NpJCcCug1hhZ;SK2U?wV)AY_i7!>xxozi`B0)6Z&|Icz>>RIgk?_&O_wBIEm zi+k~pUuwDdF_M+uC=&8NK?46;ba_OZ(o+@r;ivfj_0mLouuo@Ss~`Mr-FR<73}ktm zXn%hx{Xt@O)~n*izkbZ0U(5n{rjC4@@$0|8lo>b}o`Z~P{~$2>zkYRN8t}aNfn1Wm zzf|frxQH^-XCM1rujVD*1D+RU5hL*bu=E%(r*ixKf16r#KWVoFcwUQ<2E~7U>V8@j zrPIKk9+S%WZLV1QFT6zaPh%AH`%7Ox1FEkq{^Z>6nznu3`DeiM_VC-C{r#n9f$IOi z9#wIV9$Fu8QoRr)o|>H19bf!=o|Am=m0K9pu&evmTD>jB?&;yHR9!x67C*r-YWgJ{l6yy^HCJF}(~ zKZ>8j0{^Y<%$%t~Uu&y)^OfTM6Pio6-=j!sT@D$~61pyV%O3lpe4mM@i|ViE#!1mj zPjKl;2S1p1@>A{p`s$-6u%WoJ81gfJUG~#>{1534YJel|!V8Vz|Lv7xVC5!9%Do>L z^Z)T*{vNzLsnHMQ8uiOxBLJR|2aM!4LHz(24SI5H#+4(lv#^BVaHdA>mqc9nTV;vg zp(o!GvKD#B_wA|sO6uC3S@bW`>Xt4lX(>-+6q=#so46_d`LDgO2UAnzBHCu z)=S^#3WcuL{zP{DDUU&e{Wz177?Gxnzp}>Oqa27(Dkd*v(*BYou{#CcX$9!T(z%%)>k{|e`p8A7OFRGJi zhynB&WrBVrfu<2C6v_z(zcF)gIEM4YIe|RkC?ILKrCgiFDiA>4m4A6pxw1(lcLr}> zu=)DXNRj_+_!bg&O*O2&DW{48xifolqimwzo^n24lCN;Z$Hz5ndEc*ejf@oN+HLZq z|D?hKU&Nb~=#=(_m@fh*Lk^GxLg#i92h0#fXP<;4t$SYN$fTSC zNQqwvt&F&l=vU-qzZ4pt=zShbcY?mfF;L))cyx1eW(YLPg&W1$@Cn0HQ(uGhsq#wa z3G{$RF|Eh?kYV^O@P|%A-rubzzu>vNL0)s5Ke%jjTWhI_r9ReKL=p8tb6k7NPX*G> zU*BAW%K0my1rvp)$a(aaVU+iIU|gymB?>u%9AqsRcBK;?2p9uP37cj{ zU7!#C{#vi850I8>X5lzBSN(Z#c#PE^4PHJlDydJXM>Ww|#&T%!g$dMOQWeS1)I)!Y z6kD0RY`Y{-E%0sI|3kAqDBs6*GALt060y>irx1>eb3Hf4*7(FO^sUT72yDobh0NUOIg#SJ z0_G2~zf^M?AQjZ*`ifuOH6MilpRW};yS?qU(F!9l0z{7e>IxV|Uvts1_i}`eLu9Tj zk~qQk0caSHG1yb@v?HX;&p8R<%Sow;Uo_k+Y2ag?<0Y)Yy{n#d>d_ zcOr>GqqA;DCP8@4g?L)LY3M>~*YrNQGi9DWex@ctoS!uwLb&X_%kzK)rRcaIS> zdG2VCpl;hi*lamZpV%TVPwn7ahkB%eGa{qwvP{RW76G%Q;k;b$n8Z$7_lUBuxUTtl zou8<0ZSyJNyFRndsrJ`dZIE9m?ZU?(=Ki1=u94@72BxDog|!~evv$p{4?q=S!9ldR z=5%VW{O2X^dUT=m3Vdl+P0u7DhqWxf?Qkc^0#^~ic8)|yNz`;lk&CcaoD~3nGuIH_ z9g$akE_O#+>?M&Ulh2gx6BqyqDa572V<;xUU_T51DlAQi?P>t1YC=7L^C%Nrl0O6q z)@cMEB{e_oG!J()Kf*PAi(P9wPS^p<)nxNh=xlAGD|-l9kAVK;?$G3toSxO2X9*-1 zoND$Ni7>of%GE$WbL_;7&js1pD^iiB9q zCKqzNs9irg&eQxQHXlp1PUSV?6&8Sh(1G&!wK;1ysC zW`9HEy9IQcqpTd)ufOK&cOvqFj@PdMZBk2H=KBu6&TG|q0~_mF92%i2SY5PU zlsj6`Dp_|tc=vAHJA6#8@cD)iX0qKos{-$lxv%`&4oZ+kzuv6NFe&l!*stw4!OC3V z9W z+VGXQ*0F~QJ>lK7^)e*2IHNSOWhGt#2*qaIVe2FhO=`R0-KGo39O zRiq>yfRW7^H_^#;Mk|$_v6Um5fexWQJu{azLKg0i)}xKZu0{4#4Y0r?+-8LPbDQTl zcNX>h=la4fi|oI#+`63OY_Uwj@9AUOsj0(urv1PN7sabDD({mw-8ldOMKuLJbA&0s zE||>RrW3t$D3gf5?heI1Ra#EFDaFB2OlN;{%Q{2y)C0a z(x=}jokCidJeJSR3aLBv@ zw3*bFy#s22CDGe2^^SutG53Z?z5QB&# z6Gh=P3eE5(Z?OW`2WYGlX**m~+s4};+)uo7qg*IwHzkOo>A1{*&Q|Kg!krDwu#EF= z&#u(Ku&C{$<^wslv)!S3Cyiw=KqJ|YMGvESSFq!-E7paG1sai5M-8P)j7DyWX`aHd4liqaB zEQ_KIj-|_d$I5s%so$cwKpYV z2Gx8C#O800Ka7O+)@<^qa3G*-sfTO>LE9x2zDIbY_10-mzzRJx!Z) z1>sHV;d<@v`4`s=w1&CI`g5ERg$f$s5RL(uaj&VR#H*4kz|BKAE1mNrz6rjYg^Lyl zUX$_T)-kGRD;$fQO86Kyd~+XIU-`~yM`KrBcPA2J*XL4rsoDQ>?9n}^$Q9e`YOh0$ zPOnG;(C0Ob3m~+T28iX5)q(ACJ|gm1U^$xtw4@b5r=M27JlFI@XG#!U-@3r%Bo>6S zgOc7)!%{q62~gY$v+QOoM;^V|;0b!zXS ztE-tO3*hyDQgXIr>x?u7GKuL6rI zCgZN|YUDS<;3Y0dqU#YGD<5O1Gt5JNOP{W-Im*~PjV$XYi-#!W44ues=hEh95a8@| zHje<@ERe3+#zHw+5;4>SQ1Cnvtz!3t1Nn(LqO_;#iLE8`C2MiHJq$tocYt5LR_%_jV|PEB2lkP||8Z8hxoo#n7%(_{+kalD6yBfw~5IycbWk>EicyY))HtCtjP z&(y*@%IoK|g55N;bp$ab00|CFqIq9M)4(@=93YU{Oa@J<^O(q>=&Re}c&E9vz zF)T>vL7U#;E>wC5>GRtfbY1kSm%(97YD@F%G0T^hvj`-0ARRq?K;HcNBScIN8)yjy zydBBwfOds#jk#wDH|C_Jq-U6^SG9QX${Rm7FkD_qQL!bx?BR7rKrypO_SM*g38&1J z9W0R&)}nzk;i{``a$|j+;Ss)hlkOVq%jt!9uLwOOG~>kz8okD8d@cY2;0^#@hwqJp z&8qg1YxT>)Y)B69W^eG0aMR#?N0rgnFm%zaNifQrTIccB>g-p*!MM&+tJr zx~Sj8}*H(8EO49*N4imHOs;5Z(BJ8 znHTp+;h2w~O(%OxRsfC4P&=vR+8o95!c==Vqu-ut^Q640D(Y-n9AvufYNXiWG3jld zcRsTpPHGwTUGt8fe`SeW3o-WNHCIKVN~8GIPQ4T5X)$Hfl_z3XES%lV%8SV#T8NY2 z##~HNW$(HBGt%5em}YgCWg>ffJ#*}5J5?_x5DNJdqdqBYE* z@M)2qk_pT8ZMIC4&8P z`@s~vu|Fu}Ujy<+fR_X}W7mVC>Z|_SWAVGt{jWCgkze(j=Q0ia4OhjS=r&s3?UMJ2 zcbxEy+$!T7UGPqD^)vtpr-mbwK8f>iiKG&v=CB0uIMc6c1Ad6beui|N^f^Sy%U#`Osk|yIMvhzlE8QO=%pk{0b*_7IZ21;J&Ps=EruceoQn~78p5){P z?XV{!*cSJwvjR)#I;~*|wAG%MmNuu4fooP%rq|qtDxaX->NIO)szPIhXinN~5er^u z7vHy=e<7fPI_6o1B=%13UAYSF$gQ@wLKaP?3QDF2z@1~cyFj>mXB~Ynth!&}YYa6_d2F^Fi=(n`@j(!o($KPjWlBB~sC|!G%Dv!L$*r({OUZ3qM zAFI8n%GT^IhPOY(yavu(?gGeTva`ARR!P1K{el2KudB^q;9J_lNpg?TgQm>frO>0} zn`gfo>J)fyysGda@a|j@3b`rTHE@B5&RfmsZ0eJ(x*nzNik;zDpN0+n8!UlZP!1BT zj$@n~W2R)mHU@S;y>} z>)i-IuH&iO&iAq%N_`Aol{D1gS2KrI$Evni%4G_Oo(hBJS{>jQ!_$!6^ccAe2czJ96W3BYj@ z={2!bv%#X9lYf-t8zzYIP;5!D)KF&1idY;U>OAo+lTQa=*@DqdBUDf3JDR(d=pF$F z;zo{qQ&Yk3h#ROiV_GsEhc*=>6Drd_{#DI)k|J|+sY@i=C&3PCjF#OVoO zxN#BXMxMhK<;BpzA4y(s%3~)YGhM7z16y4yR|ct(3=%uf^ww%L6RESRRtKX@%O&yo z8aP+;z?wtt`es^u<~+g`G_&Td*8KWFtFX>IC#Ble*OtPj;sG(4QTVp3#0*a_YC5Th zz!vO@4?TPED`~@gG?>Z`R{`!f{s-Gm~-m0z!Aa zxJd2)>XltGxcnP3!VIqogh1@>*i;D*Y))?QG6BFI50kxu!ngr$29Td51Zpbq5B)*O zV{S1Eh&!MEIhS?n*rb(<#XEla^!DhU_ucAzuz)ox(EJBiIe^VF9n|F7@@Nlu$`1&d zTE=jTPCZiwE@dveoBW$jvjTfPpYs@|q8v@MFeCIU3#M4R#W9BT7pf}e}%rq75 zC%3X2<7%(IUOl@b@Z4goQ@aeH*R4kM5W2gVo_q{%sPVkKLB>RfFP(=vanwgKBatSu zD0^CtuWwZIl2tOQr@H6b59S$A1tvc)?4FKEp@ywSi9lX5zK_CG(p|x2r(bL*f9Fu# zR*Db$Lw7UfUb^YMwe84BZ0!e;{Pe?o+B|BfRH|!VfP-iB37k3uT|8g9{_b!}=6xBn zavn}Ytet^)^Zv|PSpNc*24;+hxsD}M43Hqja%l*rIQeqcyG80zXvbvl$xS+&V+44G z$*B{kbPE+WIFXH`E%{E-@q_XFB!GT16kq}y@P3(g#Ln+&&154^MOc)-JGa2Cy>#WC zwfZiyK)o7a)gQ`qMH(ZK&^{8Aj=h3JG^KRimLF@6QQ;!WYs3k+!7G0RsM9I$6iTAN zI#Z7yKR&iOjf|)appq%`*m*+tz@!M(lVX2b?Z-4u9?w$aA6x*WoUGP^h}Kb>zUOdL zzo?AESZh^8&9WzzNXLM+%*swRU?RdPmgtr2YE%31E%H&8fNs+IBi9#T&mo4i%BaGP)Xg?bT6)zjM0KSktjbi98%>HhJKvjh0TdzHO+Q?$> za$pBz=x=DNp3vM8a>g6!HbSG#8w#HjZbehHPILRk+KQg}bLL_%pn$z{*m(<{@AM)Shl6Vw9v|Ed-FsLh@)EX(f z{H14V7Voh_Sn;s4q3>VcSa$K)34_?3!?D!JqCIGj+#h`zH5Mb|i$zN>H8{65quO_O!Ujf7_rhC#|D3gw=erlkq2qnnR%7${a7K+6 zrdcY%^TfE~_cJk-Rh!H?RYdzQ$qHD`H(xMksUF{y6CU5-C4|iePG~Jfsehyip42OB ztg!}tN%vSDt%3eb%2_0;2R-@T{AV%z>Fq)K_HvwSI$y`7wQc!h2b{@Ys>vofzTfmg zJnnMB^9x*;q{)x+^MjPtDp)Pt@o*1;w2KRq&)(+A=y!&9jJ8~+e~d>;>~P7*9y*@* z5L%I5cHrH0WO_^Crla|%mZc9KDN&6HBS{7_V~cnNkdl4Vt$h($_(=eHuiC_Nq(f{x zdOKO_@tzWWor`vg-P*s#9IG`j+J3f;5x6zE&yQ!z!@|OdbV8t@rA7N3jOc*G0m3&! zA+m2`8;bd}v@RZWWY1)`BK7M1H#NT9R(f~+AkynuKN7ZbHb9jmVOAldL{%E9srBXR zD1d@s*Gkn3L;ylbO@@Qr!Q}4G9?S zpuS+%8>RKwhS%dX5v96w`p~T!6Seaz^QB*2@*gD!;|?jl46JCzyI9YPPF!YIi_Lx! z!s|fM{+^vaEWNd+k)o>hQ@VFX#33S&SJQvx@$&Pjm(@x6eIBoOJ68c?SJb_4r*J1O zm~UM4(HvcG3eMGf3>wM|ipRQcI%mYlizAw11e5_;z&t%^+m3yvV+h{uu6&2AfepreLu>&cNo3+s(9ZyNDuN zjw|d~O&mP$N1BMq)XvnhdmehQ?%uJs_T*g^*N)?dgWl*rua<%qbZZQlQ@#8n5mFGL z-QtNMJ*MJ_6!Hz^p&6S)ApXYF zrK*tGf58t6+rZz~{SYRP)BHLTd-t(!d4H+vTQzYw4H2jY{m#@unHSyoI#4Jh} z#Su%-^b{lt97081eXlNc%#`n8t(`Q#Ho7uQS6|K#G@>i?6AOHbZ^~1eO+4QHMwl~lZt$RmcJ^kl#(FfM|Fw9E11|(19yctu};%&_2 zlb(nCfXay-xu>_Uxk%46x$m;7P`c`YllVJ&C5v)+1tb#P+B5$yiKakefMQ@?w{XEiGcW;J*_+3nwXcFF+{CA|CXJWTOx>gJx=8XJfTM_w&q+(l?*zw zF9vT~jw4TBt~67|I`CS+zRd2=VF z)sv&emkI%ExdF)i%74)*b_jcMoa#Y!(8a%75AAP4X!$9G96xN@^EK6h693yJeSu7;s7( zd05n$J=XQcpe@3-S3`<*B21;L$qPL`T0KQSbWD4tQn&UpD4cHAF5N6PrA+g^i~CN* z*|Bql;S-y$T|O+m3oANLtu_zNnA zjp}>-$p5ePBQ1_0^pEoL-zrEY+;Sso90mb)_rIZ|ykjU+J@>m=xd$Uu)2r3m#d*f- zV=_&2D%De6jN3=&I5vbn=YfXuHm$GCvwMyt{lY&MCp{!e775{$%kb*nEn?&ED?Gqk+RYTc&6P~|CZf=Abj4||K!7(U+@_- zHSLHJ$jMw%u7&JU&vT$QYMPd9XL;dVr43eGPrkXu_R?37fw+XVt0M7N0+%P&wn90U zO^;c`0D8x&%UQN9AoD&tliM8r@cL+l7$|H+a+?5Rq(2dX;`QHR2hmhmd;7i?!F?j} zbsjNddToa%7ZS3kj?#gkPOqYeu{l(q%%ka%mH;o-Dh3Eg)T#6;(uNd+@&kD5aTbup zuL`8m@oaBzXSSTxMf@PaDuz5d<;{K2euMQp2bRW01{`5Cn^Ke`+?e|qO7tkA-dX8y z(qf=6++(O=UW#fTy(-xv&cyz12Q^-5gM&R{p0KkqsoorYC^Hbq6_1ktAEpe@}V=R`x7ZlsNTo%LRmV#L2*A)e!KK2{Pe2jSNjW~<8jCzZiC_# zaICe<79WVcrvbO{PO0nx>eCgt~`dOosP(obcauoNPQrRXK7t&@mevQv_bBwKd%X&MLGDw zADfM=^g0(5%P9*{Ez}&7=(|_GUka+T-Tk8`C$go>m--kKDQHX+GgB;M&~u z2XdLlw_)#4CU#;MCFU7~<_}BHF?$p%YzQKg7ph)a1n@E0PhaCG93|Jte)3`@3*577 za+^h2z+6jEto#pQ9{MKC;J*s<4|f* zWTNZu&1OOFqj{;j@0mu zd!KX0aP^~KwEEW6M352F)p(ah!u>V)Dl+&3O#yBMH-a7$$7l-aI@mWC_ctO3meZ$W zR9qYgX-E4EOrMo`xuh}yg2{f^jU?1=bARkU3B~?hy4{)aanZA<1@7;!jE;t(XjgsD z2Aj4MSamz=h7N9`@#E=(FHi}7OYlhrVJ-6{H5OF&9kX-CsTI>wy&gWaB)2sR>D%Qx z&Q<$XE+^VNDArk_xT%3iiPk(Vl&irsARMhft6{L&m~Wt2=o-e^Acbs4QD_yKbPI;v zkd!j_?iq0{2#0J=hk0}_LR~$}=MQvve&$$)nf8Cku;nWOTq>EXc(dk`4!z=mh9p4R ztjPgJ1(H@Ocq~yMbc%VmwOd^B&o@s`Bg=w}>jPMXQ}9pPrntW4*IN!^Rt2I7npkhw zxMr6zXD`U6NtsN`01jqxb=i(>7}r$Ly*4{!=h3fuWp2aStQu=(gW8()5vWDj+*`yf zH?@MnBA2qO0S_X4XKPI|R27|LH6W^iXHg&%Uhvvnoz*JzGa$t=T5m7RPlev1l9<`* z)^|+1&cTRx*p=|T4B@Gx>U3U+Gb%E&2`17u{?g_rjq)Y% zM}s>}34Q4KWM)C=Tt+H1!`93-Ee*0bHlYgFtj-QHx`@6dX`NIy_X>#}*2D*;YrdUR zXf5hhz<;44gLD}7tPb)74eq|&y&9jgnNmkh&JG3p=fG&v+lbHe9*HXGMfWf@*Eic9gRr4l@xgUZ9~tJAwX5g0wI2_l8_pQZ?vHEbP3EosmSKDEd~{*{nB#8o zXO=~L-SR% zX_YRzOWCOL3bm~xhbgpEYPylh*_UU}Xd{-d-<;5oh1`{0L64U`l)XuX_D97| zwag-_4f9nG$fA@2)27E!qTtM&sq5mIGp{w?s7!yRS(&0m;_l=^O#WpRlRd(#ect07 zAIn&JH!xpImoR7bkiujOK)=o25vct&<33#*S$6z(q7gi6Uz_PT@ZdBf+~kT)3g;q| zZ{3iM;cwZ#ByiRvEFuC9uCBM{oU=6D*Mg@X-BJ^sh_SP;JO{bg76$^CrR8OYx|y)v zUTrxrdqDSOGZmX=A|SVt2+e*5P@L9cL*f_j`9H6|jy_!HFX zO|D*oFy=R<=j-O3l)I!CTnTkTKOWbJ+JNCX)TdSJpYyo77IElI+lsYw@NGXZi0AAp zCU~3+KUZf(t~Vw zS?jpbPFv?fc^aD2^dUq0;I5OxhI_DLG(}LbCW8IN3SW_C4$&uAM0O~Zb!EvCWMOV5 z;~r^4{UXA{X{9PVTOTL7l@?HHGfpyTgtl^cn@wLLDr#o((QT<*$p#gqgUEEJe0v{; z66iTF$9YI&Bp%B`w8LhcYiQBt`kAeF0wjUVAMLuU+Q!vuuP=P zqM8-kYl;%yjjB;p6)~a>4Gq&hcL^>-FQ{UUKW>cT5uDD*ZTlcemNFCT*x#};b}Jt07%ChEG+eD<#+7&zt#FsT%i;d9+$>Ygl{P-V{=Tm+I|m8kL|fAn;29&DYt=-TK&-wZX*ls>=HYq;J*eKR^`RV~h17&2kKq3hvABBb>5$ zlbZYyybmL8eUN=-Rw`|+qipdE4#jXTTh;Z2WIjYniz%8$Z5&%Am0LmINTeB_MipG@ z8kQ zU3_1r+TOe1)-e|bi976+1l#kN^-yz35J{9l()#=ccGY-H{RSLeXYEu}Ro6ma_nJP@ zh!|CyCZ7ad5`cy+VP?jB;$;@O_BFXE#&(ksdm6ez46b z-UUb*j`laGKhqba*wkdvoo!O0?7kH-&28KpJjR7J(lGH4Z+e%SfT1N=QER(LA9*mNqJ`Zku%jx*U6Dc?LDruX|9Vvcme4xhC@%#;lnwT1Ka#L^ z_YC~nVB}wS6g70%dHlL-vV5BfS%b2si_4uL6TUm13>5GB$n}tw?GI=zBDBd zIKFmcn}98yp60cB`AxokS3+oA-}IUet6)dfSSlDKgWBwxMN%*rjCF49cjxrz<2sKm#~W-nj$k=zx;{`^bf>xQ zw&pD*Rp$}tJZ-x#xXgu7I}lWx1dlHsecek9qe7jLGTc8MteQcJl^Y_(1~(kZJWL@! zTTvYoO&-x{Ds&NQOp4{^dIpajbh(+$^ORf*$?K1>EB92_$104*5Q?};bpxgsC25fe zSG1`+p{#Lsi0cD7>hP^a(E#a+z;oPWqxE-&u=gc*9->bac8zv#Qnc9Kqxn;yxjzM} zu_sXZ3gIrIK+VsLxY5WE1^RZJ9|%;Pq;^xFI8*eSK&Ss9P=D&qno`I09c0^=via5S ziR)Y4wmmVxFtltkq9wMv;b5GL0+=Wu;Y5nf$;nyZ0R@mU>jX1RlCm3}7E~icJC_Ub z)^FCatzWsI_tr!;*RW$vOGg94uj1pbgqWTM(ZIVJeU zbN|({1uHmwG%`^mV3L&nF=BWoip)b^2Ft%YIO^oGIX8m5cHafaRw-&+cXMMTiQvMP z8HO}LvxfAVUeSPoLw|>Vu3#h&zzz+JjC_#+;H--Pp5Yt{EoHgSgFqKE<3wD2(95t+ zQYp*8#GwBnp+8aCwI(csl(MtG8wacA!RX zC1FU}he??(m+MC3NKVYw79q&+FFUMPu8b`dp$1^&&^G|a2cn2DZQP9|)Ogf&y? zP8nUvtQ~JVREuDu?ufp3C7Ex)O&QR@2N;{yyuR!LI#dk;`|Hla_SGU5o!iy6>Ulg{ za~*XqD9%onrc6fpdZvV)&1^pMPB7zjujXNHhacJU??pXh2cioser39u4MdK7yI)SWAVOblMs<-F+Zl>{P`>5EAm>z(b8ig=Xt zBy!AOiteWPm7}M=2t0}XH6=hVJ-D~>-FqYY_doX?@ulH4s>UG+EB$SHmPT1{5Dh6$ z%OCz#|MLHOZy^Wlh;ERm`_I`1Kd?>zYZXz{QITL}BP)H(sb91Q{!b1b&~5!ztAy5l z^FN#U|K}_DWi9wU z+f96sUv1w%-t&q$C}oMaU6~U4mkWOW;V%vUhrRa^!h!8>trAbF1p@gFJj+D?7?hcljGb3}H_kEuG<(@Ay zktF}@z4qFxuiql_xWLU@U~gX7wY2H+$-wnx;)k4ByF_$Y8zV)B|s&^XM`4U9tm>}oBWq}7`rva~LKUdgqJNpx$ z;}3t~XV>}da~TAi=rkG0&kBJ*J{K(w&L!=S@go0X*(wBPS7F88@ot}7xg$T#^g~)9 zj=F3p-k%rf-uKR%^86}cWyxcH{CoM&{xtf_@)Tmk%q>q3l*fgz44l>3`d+2U;?=RZ6|!zt)PJ zr_Yz5QoU2P{x0?YnPg&DNuCcx2Plrl{%cVY3BEbgS>4I;)93h=4CkqUvXHIMux(SOVEcO-yV3%g<- z`!)CR^Gp7C&s#Zi&3}(;122BwiI$`p7dT7gef#j;GY+>dMkkT}G|j1%AB1Spyojv- z*XK(#auTp3Eyv7X)$U&e$`Ag@lL4+eX_L(8&u{tLQAzntDY)#=N6Vf68qMf|*!2UMOUh}vh3@NCJ~uBsO$Gx6o0^*J z&;}asTU%AYSQI6MQo3B*)uUil4={(0&$V+erkt*5F%L;vZCUkucqW2m#s3rwhrM~x zd`G{A@gD_h`||R)H$n*kAc0Y5(9sSZZwhbI1-0}YSt{8tLPJMhpb9?&d?GV2t3}A> zqgb(~gv66dFa_Fiai}6~u$Q1OiY4^kTFTF^oT#$fvL9%ya9kfTTTZX#d$|#`JBJ>O z6wOF}IATMSX_o0WJFQX3)lq8ul)5e1M6y3D)M0=pIn z745BY*Lpw(iZCIFQpX`Atk)bBCkhksh4Uumlm1Gi&3xIcp2!H%;;@AsFKu;mY$P$M zNb~6oeLyj=^@8we+|nxD^IlDIYRtE@|F4(&&Q)-WM~|t4?IUbHy?a*Swd4;m#m=Bk z8hubDl#_YxEH$*H5yp2D#yS_Y9RRZF;~{T3N$2ix(JF!D>^u>~O^D}~<86(?aFa={ zE;Lt_Egvbh;~V^TDEGId&rhxA{3eip@LR{Y%I2=(Ky27)?GihC*W)APFA@?KU!1Fa z?J#{0x44VXQyR!t;}QmQWk3Xtz&?>gZ5wz!Qo3s$({`_~XEZFjsn+>0%JqFZy6b{F zh?_^P$Bxhk%_Kq>a$UHb_+J0%H2ztC00)`_+<l>rN*@QZVAuw66yU?sF7Ta`m zwkNL#beP3~CKjFw0K;M4lN+a0zegZmZ(pQNa*$5{wZS2TXK;kbs$YSw>wQd`HFnjr z%GU4Ry`9oeL%!yHr9NN2@smp`z6DrYs6HRSXt{yb2LeYIzBX(mt5}vc)K|T6!50S66!T)EHN7wxyImQO6sK0+46IYN_)Gj0bDtrbf9 z$;2)1mMnQ-sT7uoe{1{gORnzcj%}K7Y?6oDK_SVY*Y^BLj=Rx3QedVPT*+x3(bGg- zf{JewUe_LU=#pJyvj_64y6XT=Za!rtcT4y2Tcs7dyuvy zocnnlm)7EEit0y?pPK2Za=CK1U~4{jHJBeie%WzuKsU@p&gN_G_b;~IKL1OZ3AG{>=3xSp@)7vu0A-C+c zg~8buK)$E}QTT0B8NW{r%-_-3EbwP1Y3Y;+#^2a1@saCe?1@jQOh5aLNI%Dz3k2Kl zhHV8vWN{!sIayi`6x(j~wR=%G()jG@9pXc6*PSz-#5-y#2Zez^^-^T8Z)qR_U+A0I z{x7fg4){pGB%uvgE>1|i@MTm~rb&XQsz?G?a_nA|#yjhP+Ay9TVK&UBe@oLXE3K_E zcKyTQ)2jdF(SIz#CJ%7YkpN3MxgbA3zl)leI62Wkb6jjv--}~C<5YOA_Np^fthQdv zEJ|e8#^5#;``-3`>OUWKfv_b%g%LZSNQaw}Y-(=K?i}Im(M|zl71dbN_Xv@AGchMe zJ9u!Z(C?@W8_5X{oZEtbKaxFNTJX?M{m9;deH7XIr7kcAMs|0rrz*J!AQXw{cx{f8 z{Psu@skDcOb-rR}imuQMht4>4h?oRnT7PdyGG#{LM_5@uL}I zeQp?9)lHY+iTV1upW}xCR)rAWu{J!fOCBB|Fqs1Ux04O|WI7E2R4Ifalf4FDOE4ml zkbLAZ?KuDC%7Gc-?#^>PBZBRcm+ux&ABYopmB1PA7NqMkrecC&moKN~6rFfXD@S$o zFi*(?s;G*cdFQd+p);E;yVPzZtgk+5S+g6pm^Ka*!P0NTXn1O6DIj}A02LQ2i*7$^ zDY2$`j4)5pZcvdWQ}0ynvAu5=g0|SbQ>C%)UV)s4upNzHeytWFo4TdMQ@*XIW7m0z z+F{kqJS6_KM$$=iIeJ*){P^$t9yBM#ohTzF%JsY(WvZ&GX)A5lCdeM1Y+F><^FSR^mqY<<^fa&CN~N zj#hu{e1uM0-!WQGKm6pAm73Xx_-+{*k^YRq;kl!EPj6m;^V1i5tqK3jN( zQf@(rr#@QQU!_`_h&5rCeRHu`@&ZUD-f>#oDi(5z6>ht?CNAhAo zD_-lN>n4*6gJrW|#EB|s_>X%76zMd8cthiH+i_Q+uX-3|A_Qi?Q0aQr#D_8AO=Fvh zD%Txe+^1<|EcbLrN!)_xCq9Hl*E?2BnSGU2)vCzpiPM5cCh^yl!;J3&;rdKg?_DB| ze)b*sOQM|Gt2xKQhdupw_;u5toRQ~^b$O$gbkFMwBz3}tYQn`^ zE1eY^VHOzrQTiLH`mObAL5hlzkkE)+z`X0ciK{y8Jd4zdVDG;Aie8g02`{;-(xWQL zO3zrMz*B3$mLT0Evnq>6Zh5p*_J<)QD-R@aF1S|GQg0vS_Jh_{iO#7rm@gpkOih7K z`%6VVU}WeXw64HLfL{8!xp{ub(Q=PXJM7}{Flzxtf1z2*P=z}b=v6saC#NEiUH;um z(1$>^dn6zRIassSIMa?W9BP(3h<+x;-(Dr5E$fw7xvd=Mz?5ibTHafQG#u-4^=z1ZOuwCN zKTD5FG9q@gNQ^|`^UrOWilvW^%dbzzbXsFI+Nuzqll(&4y#-_IjQI92kksGSG~PeV z4XSj24fJRPB#3#yw6pQa$!qSzwhiY>w`Q{AfT^f@aTefz)TEU5kE`0v0h6}7$Wp89 z88FTml7Pl>JgV6if3S4-Nkgk?WUAc3N%tEQ(d`~D^jZzh1WEAU&2-Sr5wz11XQPysX5o9WY*`K6Y#nx;IO-1 zVZCm~3A>#ia}S>WOsxDno5KCq8J{2%0ykg^!u?KaZW5(M6c$}3WxH_Ns6oejljL&> z3>F0LIu`U~f9|>rLJsw=Q~)YO$L8&!EpYu}g`bkrq!E-kdJ2w`HK-5x(9Bhp6B`?A z6AmV7fx1goHC@-#oDU>XptVI1*qec(R_N`iJg+sVC1wL&u#(Tb*7>3@615@X_U>b) z+b;Zs%1gCVLtF})X{`ynlEYNi67R=6yYq9*yvNYd4*CPe5@sCR;ZpAfF6Ez2wk70g(TiSR_Sy0g{~ zdrkL7Wd2w=N`g4x(~Ctu1jQ#4amkhqY1SoyX2~HyS~ewf7#bRyf>A_URlD1wJ~xwW z!a1~xScHXjOyXUQ3w2m-{o>8=JFwsI=PS0lN#Hv*+igJ_9NdnWceCB4Ix^{(`fqBw zMF$BcJypfoB6tneT>8rls_u2(>)tIiNSVLccOM)m?Qi#s?a zu2eC(%1@GXbVP=b3NKTu?TN_XnXH6AR@}ZQ3QOMYo|v@6i9*Ve^9MQlU*D#h??UC- zL%8*!QBph{7Ox+p%M~h@AEC3WT~9|)W(lb42WgyoQ}@z*2O;qSUT6W~yR9UAA&dVp)`xmana;n!D4rw1WT_}dxFQrVBWP(UsSj%%$4^IU z(HB!>wd`=^tv--Gn7Vv=a}_7DYxy*F$UYB?9Ma?Yp%uC3fmh!@KpH<_9(Yg4YCwSC zL~0h>Bw3Y=M|?I-eHtg(jRKQhWy6@|(QxEYR@q{u7C;>9+}T_~=)FBq0c0#27gx`8 zdcqJ3MA8y#usZdjA8DOnp9>~Hml(IjPUked(F^R{0)u;J0J!oIHDqP{HWnf5RwyZa28b`9iy!hH#wa}=1vxu0s$k`ztr z{+n#9d}i4bXHc?0BxjZoS4QzkF}K9Tb=0cPzFbAF5lt8daM?PVXwR=7`7V#4>+>zn zlQUwP@mIA>-Y3K-k0^vti6aC)J=jitWDTG%pQy?SQGx-O+F2mNgEaXSeMG|4-vES8H~vWTQ2iW3 zRVHBeS3?f~s@61{pvo|;nXJ((Fl2YxIcl*)kps*vajB7X2kE|H0kq$}XV!DbKm5~5 z%$2H}iZMr{%DaL1H`*Dw5gs+(O_LWUYTo+DXYCpMD%L-)7CmK|-jp7ypfEfjAa$^1 zlV|KUET!Rm-{_v?*sgf60qUX%>J8iE2@MQ27vVd1mIE>OU~~19aD0)Z&ZPJ91J3!+ zw;TntWNwo;J8|_S*biSx7`$qD&%6fXF|ndNzT(%L6we-xX}!}GRz7Lk z5u%mgGIE3v=Qv4R0S0fHpDp42{qSQ+Hyi-(KA8^z7N;Ya>;9g4x)2P*?K2L1U>^9{ z4W**S3aTJk_q-(2V}#V#F{7Xm7Vtv$#n@XXp};HPUQNWD)b3$vWw6%r&HTW$%^s#S zqyyJ8j^4SI68zD8o=*L>LiCCroW4jC7I%s^-*L+@tXJq-|9x^@30O)Ple>p+_O(&- zb-#^%vJm?P%$*Zn_?J~8nZ_fNmb{l80f?2A?{XK(So_t4n4NL9qrZ{i*$z{f7F)me zLR&}Q>te&lyQ@uG4HkbgX(AnCJL7lV$yFn&$-fy@niI~HupB0|mOEnw6qU-a()&x( zj0CYq3`ot!bV3sgFHrMrCTd!CvjDd~cNo8hZ1Vy^8x$B!nheUN&6dX+OUEO$9NGjY zO##vkp`O16yS%*oE+tDB;6=B2?FC%}FMt4@0gHXWZ9?3GrO^-2i#9XxkSo($N6QK_ z?fKedh3mfXE~e>P326(2`(2o&?|WBEU%S>ni#y^a1mnfYMq0=SHI=+OM<1Y64SdOS zc{Ke+LNu3A^y85i&!w)CGOel@hpKip-*bQ<1!o2`BU`EBhu5(lIM>B%6DykL;RX@J z4@piRlC^_2KW0L@!K+Sw%-KIQ{QMX1$IQq|F#7mYh}y8nN^3^Cnvz{MulcMvr49qs zN)~{ZD*^)>K*Q60Q0>Xpaoik_B$(a(V6K-72F$p|0^n+8%l<;&jAladH>h_6B@VAR zEtxfenz-#xYtc?ibtSv=aIRv*1MZYEP5MXYL>@wOe1p-H>;3fa=P!c-FDLzMxFpP| zvRa_&#n=~L!!wl(;#?m|sI#`Jv`%QjBdAJvA^5vh9+`@;=>EaHu5t$D9GN$q9r9Z` zj1Xz@ZRiP)S7nva23}qR%wiC8#m@C9aaF8_DqXi5 zyMvwWY5x*HF#T2~M$QUY<03CT=8c3pM*DeQi}aD)5Z>dt;z2Btx!rFMsw_`kth=fY z^)pN6In~)_7RIZ$kYn1)uStaql#84DLW)85J>^(pO{WZcXD&URVe-N&Gk1L+w<@!) zp^xHIu!EK~p;&trPhd;r&-FXmJS0DS$f4^=!gTgK*-wgEairlCv18~rs=l&T2#GAL z0*pQ6&Hf=4v71DI45a{$WDsE6pJe6*bFXD%1r*uUavhqW(pH{eqOwuoj=B5^(Vf@* z2&hS(Y828Eqk2Mk^|_J==!1=OorwAp78kp9^!Y%4$GgIWJA`0RrUn8oXCPs2;1&Ny zHBTj)in4_|gt!0HRZP=CBR1H&=OHv)>0{=kvZ}VGfqn?DezufwXAlkZbggSa3NL2L zXq8{c^-aSbQ#j>4%i}mH2&^)Ze9%P_(j%>uQ!-si8f+Ndf0-T`@tcf;Cx(?8Hdp-Y zf+u7s|E~Y;%8RQzRH!HIQdXo40wpNwO!O@roZ=zB`hb z16x8y)QySk`e$^Z7CM5g#y#Ci!tZ;EMDfQ<#Z+N?o2+*dPIC8NZsT+ zpueewH~C~+r%;&Khw+d)>Ge$&3OOyf8^r}~1zleiiwTr$rm=w(OU5}M>kPZB>|>|$ z!XvaDrPsdrb(Qyg^R9hSjn0Ee)qpvHKKrt#jtSdMw@Mc>8fQ8xZ{4OpT6C#<;$3T# zw3*^`@ktdnxUvXRx(=(EGmu8PrNwp0Y5#hGL_e|AD;!xC{@Hpv8%zD5qZEvt&KF`V zs&~AsB*@RN2BvK|I>`WA5g2L#l`R-wf2miUCd z{8%%asK7{;&iZH9_j5`)i?0GZTr1iFtJP!5RNF0KH=^(X(hWi$yMEY5li|fg-Jcs> zfVe)X_nqEbiU@?XUT!!AY(6@NIm0APfRMP?Ep@93{I3X1c4UI21Z_lI^ zQzD5ql+Z*-*vuDJ2YfWIq(=@=W#+6EkTA!yWazZI)S_$LZ@>)XpGl>CJt5d1Cp3Um zwV3O9OB)^|e@8Oi0R=lGnIWKXmiEJt3BH>7%rW!u-9@42cGVt!et73TCJt4OrUD-L zBx#fB{ZRE2vfc_}>sB6OKI4ao!?d8dW5x+eb3H+xInk3U7)NIq6s`B8Spa+M{^h_D z3B#ol-l2m%>G*aS-d=cjXGM;j0Cx#M{X{@g#`*9-fqwQip_^RVoHky?u!?J(&aR@< zvv^dwjc2~z zGmdZf4B9!241cFj`q5k##7l;jJxe!g{dtlHKR@z8!&)cP8bozo^=-qF9H6Tx7A4z^ z+mVQkq$kdKg$bDeE<4f;RawPeGiO4_+_a$L&lU$k1v;{1cE@|t<}O&Dd)E682OCY4 zd;+G}MJrowxiC-?Eefl&rw|Fd{03y!5Egx%tOnn+&!(IQm|NpAJGq~*pcslY1&<>t za@Wx3ucn^I9F}!dJD@|fO z-h2gAQ%4KkhE1Gw&V{lTlgNIi?0A*oey)`#(Cp2NL;ad&(es3Y`Mqc) zj`N1c*LZH}NF^z=dvv_|$}Oc*(Y=nbTQqd&Sg(RPeIrCuXI#TTuDr;uvLI^-F}W%n z&QuQU?%V~N)S&r+hD>XYOTDWv`6xZ$Io&zW3~nn6dDMxd*EEyoTOsGe@l5Xm`1ZFa z1sI-RZN5vI84?!;$~jt zf8_L5p=r(FxOqk!NH&yvoClB~pXebIG{yAoC`pT#7^9CkN!{~aY7u^=yz*Dd zm9X+WJ=M~CPmkx@2}I*=!wdrMh1Tt2m9He2N+Gt= z*mSmQ>jtD2&ZTaMDKlraIE+ICS5JBsMUJxHa6r9z+JnvEBbE44=W1;u#AT_Rr)h{1 zx|!T|llP1K^9@VWtRMi|!*x8%Q3EO~=ovbwT`>s^sfxFzKaK+t^ow^5QM9MsENCAj zL?SCd*t;!Lt1(|Dk`qbT{mykcEx56!lVqEp9EbD&&X|!i-7gi%fX6d>(1Uz)T!o=&j!O`}cRDOmyVsFbmJHSb()u~PyF2_G*Pow=GU{yMNRQ0oY^`Ym;wC26k=_@q1wdPMn zt>rkyjNXQg%Dj4G&^z$eh1{b5c8e<Eh6tOhl43fVFLBv*0nHJF_HIKkk zB!khQ+J5vs!LYTi!WBI^Ml}K$Ru_1Jj@A}~z1-mc2Flaq2bPYWy?e>6h2fP*M(9Yi zqy+;1j%6^Q!F--PYeGTwfT3#?m0U}}N9vZl-1NoAeMe=SvdwtB>sFClx3dg`zJwUG z627^|ju_AFv8VEEqT?U$q*cC{x>6va)7pkpKZuFT)#Y&OCz=^ZD{v5Vcd-ZsW;09+%I0aNP>cgTEcK`Hy3({^TouBkUzL2(W0ttw%Tx`xM^) z==-Szp{w&S8x<7J0%dHW5Ls3)pn4ll=!V)0Y7hHA`)2W|4Iw9Lf;KnoKZ}0aOgbSJ z9^pCB?jrptHF|Tguj$BG@3A*_s(Dk+QM7Yz2~V(RG!?BPX!|xY_$a;L$}3f$iL<2V z>xyWF9CS~%qG5HhPt&)wU{^H%#*N=YD(7z|_5}`?;oC%~#Uc2^hX*FZqs_e>^>vrzQd3ibZ9tq|daY$O_C34t|*|1+uRwfu{cwI9rL`#_3r8Kbmf_GwL zEQ`mOZFucv{p|4f)R(dL*6~?kc;}=_(ibc^94yKq;89Ak#4Y&shfo&o!GMoKz1>0a zE##KFw<7^!!F-tD*VF*)dngLNJ|709WN!}`m}y?kE)CIwSEg^=D}-;*gcCRO&b$xd zliVn2Y}Apzy4wcdxHgXvq?>8Oa*wS?@y%}Zu_zmdYWd$X*D;o`I`NPM{Jghui59d^0|04sUY?+^q7(og z#n}fs-hcP_NGV}9jFZUD=UX~XeMb2U3sG($-by?3rjv~0C65G5XY2KlPLaS)f0<{P z+)mp@FO8t`3UYloV_4L|zpITO;+dt?pnb;qnl8qBOf^qD7JpIUf{jgWxer_Ji(YCD zR6X_WmaVWy_riKho%;<5J=Pn+hNS_tnX-pmo75{L%$Qhf%(-Uppyh1&>Pkh)Vy-F+ zcPj(9jhgLqLy6?Lz<8msuRbQuSnRtp-K_Mq3k)BKW`=Pz!Xs{EajEnP(n0mMyHMHU z@-dA1w1*Gz%#X%kRo>Ry;GPBA=A6B2MH)SZMn_*|@ot3E&RU-xQ~ru$^qm|3&=%*J zyp6*Lw(?*&8Bl)53&9wt5}%C)J!Qu&2TN5FV0c$}9w<)$c;}chCWrWlh%^w#k|TK8 zT?^ovrV)mO0b~m2CUdRVWR3uZ=#w(^L$Xf<7bF+tzJ!b}oh4L)tg&CH3phWJ54HAu zvwWgWuB^x-ld~Z_64fwHGYsE+tvvYLUmrf%6oqz50xzIo*v*c1)>)c&Pk_! zMIKf66+aYw-B`lHQ;e~W5jgO0E0W+TGm+7`GP5kX82)R?{fY(>QF&dhYFqBcL~31+ zQC8iJ76s&lJPj{Agj{?2+uh$5e*9h1ZF_D%rfTFF4j6E|T!LD#TrD~MsZ&oZVcaW= z?yP6!Ri&%h${uDI>($z{x~A2h#Tc8L6V^{}*4;p`$y?YFuq+tG{-I+*L7qTe^FZBF z0M_@6lMtD910fp&x776XSpZiQ)GHdoj@!Zlzcr@NYEUS>PbFJ*dL}y$B=aMbR0rPy z--5?$$AyqTRH60SxF1Nv53nkdZh~kIiNAV8(A<#ZcI9AJT+Hsg^6pj`ih5&MG&KB` zCPw*XWJ;uQj=FD)s@*GNjT;dqNO2w!~k#mD)%D3lr7|R@RlKfeT0}RbuJ0~$CI!D6k?pj$6 zJ_p=6WnI3|y?=*NBA>T$*Z}ph-y8=Wdoo+LN(Y7HfL@1ofX>H40KiMA_d!c3Ajnh* z-MDl+ABhq1SbzwK1%66bCO@!uIMiQ*dXo$H0Kx7AtE1f#u4~g(;QXZhN#3F0u3l|c zgqAUQ85hK+3}4^{S6b}#HZk8pfLb^Ta|%E!W4fY?ANdHhs%9vnXs;BlKdA+;MK_|D ziuy%#KwmC|av};uV$lK*vw3gk@IHi24X&SVx@-OUr1rEm_J{znoO?#{aZ1zfF;&n5er>T_$;`~`X~I*2iXlu% zly<#-h+ts6ykaoY$GA|6J`4v=H^8<@F0ck6Mlgvl*B}^U<^DW}17FrbXJyDmO<_i(MY%s_uc{Ejwj?00{4WNArO1p?Ta& zDUq}@p$S?!?faX=K{MD#!UnEmb`|2Ff!M%Bw;3!#w+!WLezo| ztcs+WWc)-_E&9w_UVf0^iCOSl)K04k*DfB30-2;EH&RZ14Q&0u9%4Jfv+*7t9yFd+ zrwc1p;p-3#C3})N;qua;U0nSW9d6a4s9W+FQ{fC9h$F z?uo~vPz(O}K!C)d`qx-z;A)0hV1g)WN?mk)(^ZR9&Z3T^OLK;wCZaLHtX@l&JD%4g zLa4k>8Ipzf{Ah2)bo6Gluzs2wVpgNUDQjT@fmc19 zNc00e{Y7JYZxKpLC97Im?t&)RVFl-pA!Z#4m5Nxmb#T*-f^BY4Zq34teFcNg-wue-HRTdUmUul*xrtat^4j9))<^i2>|N!@VO+HI$lEE2e9 z?XmP^ZF8+TawM1;sWOogMD;-=aV|Ev)#M^OwQtnT@rf1f^BJS}wx`gakZi)KcwAw7 z3jt)R_3ZwnBjkfLPc#CJY7X$2o7&o(H1q$Akr4;R+V161%Gv{@-&pirB|USwIr0BF!!vh7klL28eDgF~AUcI4jxoe7EBnJgoH@+@AWC0b1=gsH!jq{K9>A zSv-@-Sh#O?YOmj$ z{C6C|CD1}zsW>?~6(fEKLBaIVbja-C7`nE0>sg9ByUC=}d~c!1fSzljG97-CUrs-J zI3c-t;(E$jTp8oU16oU;G1cJT;;q~@tK}~Dm%|bsLJPwATdDIA_sO&@rvSYVZL;m^ z1=^+G1yC|=(AOum<_-Go36N@pqP6gC^x$Ii0CE7iCLEvPY5=ReBO}$d?jEd!T(#;i zHz{zMT;$Wa(wBoC{w?N%vdYjeT-iF%SLo%$hvGM|%~R=RawSTlbawuoN?qjQRETqc z5Nrp&6t4g9>U7_zro5_jZp|RFhUiZ~5>G8dj9a5qqqt2}S<@4Zy$N03B?q(&C|EcJ z5+#{o^2BR%8E@J%n$w`GM*J$Q>E}hf%j(yjSrePnKX?EoI^g|4#C^#q&TjMZBM2N* zEnFZ{>RG<(N?N=sY3_IO)3kNXZ^fB^s*EyyDY$M~Q%pO=*0c2KqOXp1)@(70!Ykfu zJu^tirLOI3s@c~~uWFwl9f|Isjb?`I2Qo2heTk|2FHjACQs#+5fKjuvvK3mRnvWCxd9nY4#P?gtu<9j(j+}5M0d}rg7V0N z)Mfh_TR$SQBGHaw6H8V~^*8tj{Y5ZRBCMDC!aHfDBWL+dUj@-!;T!opDPI*_i#~kv z=d1h)JBub{$cZFBW~2o9ndU=#a!=0YobPyX0DjHEPrxJQcpN=iV}FAD;ZXnaDlrq( zC0foLw(;2C8rmh?5f-^lwLb2bH_TR)F>C%FJ zY1rS9`-3X~`N{^ASvj)&n|7A3%P=(utBnylaF%XgjlbU;)u7Q6mGloG?Xe)V$ped7u+pZ@ow|4j1#m&i-dcLryl8T=aw{*}2DVt_Y?W~z1CU!?3qXKx8| zAl^P?2>!mmpS}+Vi&+9Y{(nFEk0k#edH-;WJ_H8Y(Q7hXE0~NZJ?wr3KAUgc}d9eq-{CdFh z2ryY>-aGyAm+x=w`@)-+9MqK=bj#f)JYnCD{pGEW2%w6J9$PT){q9eGYwF6cjc{R! z`P)DF`TuR|3kANC>whQpo!S1!e&0y(zdQ9^nEZc~ek}9(+=3^8d?Qi#nA?!cRjo*M zFNx%A{-l|Y5YOnvZ-oAjtN5SNkmdZZ+(-(A%cMU4MuPSn@{0~l%{!4?&;wCc?(VyF zPV(;(I8pD=){^9tLo`YU>3_5mF$mdZdnm*&0?PQKxA$4ksbVoR@8CS08g6p&vX^tW zABeFZa29s*WQRu|UX}BvU%L)>)_s}%r@bfk9NtJx(IqFLy!rPPqIJ8Qy&zR2^2tPe`E;ju1H?{j8>-*a=Okoa$YF#^1)$TFDy#%Jqn@GyO zynG=|E{+-u6w$zxk`x%X`Ynw%G>p{w+n1>*E7ua*DbDbkcb6V72n1_6M1OfRR%>*# z!Nh3PwI>%->%$*+vW{^+=I%}_tkwT$a5-Cqn#$xB3kQ23)XVGsF^qm!j{KpY)8$*a zV%t}Jw-z=^cbY(lFuK=eG_b%cT{eayQpZU{6{40@S}G)ho0d26g-=(iK|B$)Xvd^J zi3ehDkHmgP(Cb%Ag!dKWH@oLH#yL(HVjWMLLud4t)vVjdw7NV+VH3;@MY%^?`F?6O zo_9gamH1#$D<7uz1*?+gS;y(r$okdkF0Dd@svtnu8Es@vXyNl*4oe8&0?;-ZI)t;r z-O$^(_O$K;Wb>|n5`KAtSRc*Jg*1i2?Y2?twd}hd!kEIzU(4!=Prx9mYX8V5-+4Q6 z@#r0^`P;{;KKpRhPJ#oOd%v}{B|vBw1UWAa%#05hUrtXL=4;ZbWnJMo0NOpiu14yk zFx?RQ+BHKDzOniz^~IkaVp7~RWYI-#pW3TDdGH&}l5ZxQ1I|!4K#FG&0+__Vam){w zD3(A0?6k(ugElp!`6yK_BgraIAY)rkWnze(@Bwv^oN{0uX-;NN&ZULQ?S)>$FxfYJ z1SVMJ_cmx3y#B;8-;8grBo7A`K4GF!;ra;`IrK~`Z$k>LeDB`bbkEV=UenLjIkE(j z{xe4t*6021cfxW6j#FJ_SOB9=SXfyb-HJhj&xnaAH0q^_ipuGP%@&i3I+KysUMn&A z04RDg8x5X26?xzwG3hfUPGL4bKmRvNqC44D^(iM>TV~9X++1a~VQp|lC7l?=?&LIG z@Re)ut%o;?Zv5n$M7YkEI11m~h+i*f1{gI16vDBfs%WX6#@f&_J=RY86*qDsGT3W1 z#TI1T#=k75=YYYmFq4Q=3$f;z0gugKgSS&Hf{4 z^!KwvmFtaG<5vQ8%-iFW;g3rUkF-i7D{Jx z&+wQkpu52IQcBQsZ4~R!DW#!RI!qwK86gK#blTnyPBNx4+BWqB`}zGkPSp_B74JVh zfG;b?(m0z~)-l%E&KOBHBwnB~vLyNMoI&88Q}Mt(;CwbsC{F+*8mvEbsa0*ET(;+t z1x3xAWtW)lzI=|_lb?Fw)f4pm{weMFmaHeQR!3)Hr)4NPn){E7j??GktT4tuy=^5R zJ1Fb0FAaixYfgxkqlTE|V$XmI6Q^tp4;f(DY7*~tPltrw$&Z6tM0C4P9n`{83)8}OmX`XVdGHUpdlyXg zNOuo^t#ex$Z&oBK$6Q-u>#dQf-=;lf?$;0e*KK&eBWK|#zhL?DBq1NWgsj5BQDN-~ zqM||9m)~yy(oxpcE&FPTciwp*Rz+F7y#=Y0X|L$ax`i4svK{SNcxG=cfSNVUzDdoW zA!cB}bA5H21z&wb@x@Nppo|ia_~@e(;*B?mCG2iFtWTrohFyAirr$-7Qb26y-?8NO zp?>p+;_ub+bA8~L-TPyN%fz)oJ=<1@7|hoiMm5<~%$co28(gt=duJ>YQcItQ=a`|P zSw6YA>}X~yHOFtBC*ToTqu=hlKzp#6*kM!9;m&uJ@SiVAl@iBB45!=3S0^gLq=pw| zN|(N(@E;lQs4JRu*a zd+6r3A59&ick!6%vTfiMZO(mVrzh^QiD9l=9Tq+rNE%qO2CKRv+QinRKUdaZxXtQt zSFeX-eY*G8H7lj_vL0r|TNp);p`Mg0t=xmoi&nDMvWrjZt>t}3?3u)G8R(qCHB<_R zD#Sd!JoGLgub9GEdl2b^E1j!!9G+NQ%2l_{Sf|8IyAE`BpAvPOF|pk`I9WRu#b2k? z93SW-e$>Erx>H^I%_}Y1qxv_lBc@6=mbgWOiSbJc$`oq#Z83|#i;G*rsIs#~xMuw( z(?x#FAc?zx`(*X2L>l1)^dfx#?vwAaxjd)AW7PCwV>MkgPR1Aq&d8?o4=M9 zQp!5?lAC|lH1D9Z|L*nq(UL8vGK+Iu*O&BL+&#T=Yt<9qZ&bw1SI*0~k3Ok?A~1_z8HqjEEKu@{1JVlJZB5NA*|U#?*BL zKB<3g<@O3^&F^q`j>qFE3n!Of4|MpM2_;@w*L@bd(cwfaX{)$Za1hQFs-@-pLHbV= z`;){IW(Os!OA8iuvp$r%XF#i=8bv;+RjLEmF)}8f*YYlGW zZ>k(DA3`H~-5ODfVN6AQqL5Gpt+n?C9~8(GuihVC({@W=yE1fVVw$6TkM($AVg7%i zWm&?exc16`bFzSxh3D|g-Ded=XXza492HT@r<SOqrb8Z{PN4yHmTb; zlvh_LMJ|_N}-xpCc^5Lnm@w`2LNweG@!=XP`ME{1* zrwE)uk!AM;ZQ~_4c36(=l&XwHD_ta0{DiShD`Rnl$D!UuOV+TyIu z3{)&MOQbHzhU!pua|BRA+^>irYtoZ*UReZQP9+5_YV=_r?IC;#u;{Ogrgl)Fm6;1q z&ys<5p4NAcL#~r`0A(l=6+_v18{Jo6(hw#u62+U|m@j$O_VzJgX+xC=_Zmcb=e1iX z@b0!AD}^-4#;%s=w++EKz4G1BZ6n|egcwNF4)oy9GsWi-(?Q%8t98pztU8I>^fEO#!uK>M_=IDaU2S)ACeQ;i9*;x+td`gYJa!jDp1 zdPb@1a)E+V`^=(C!!@DnwE)b~1wgvk2Ls@NjGUY~8#?&8j;Ir}G&D4$uWOF`1LZ9= zYd7q<9*D8767KBN>M1(w&~d{SV6jae>+}TT0-zjF*{*(&ob+;Xw`?$D2B8Ilr|9C* z+4I3V0r$uSTgU(A5fbA%D`3`1iQW_{9o5A&K0>*t7;&wWuuJs$cW`i(6tz1j@l zp)-8PDmpWFPiw{7Xuojy)B>-^XuGMDitJS@6&CCOa1jSOTOriEV7Ko5$mkFq+ zaPFq!{Jqyn88A=Pbezp;%bXB65A=(Ppz{{zA*75r>ch!AAX) z82;`k=$!AEZ-kra&wzflQ84K=kX0$IHnM7G{0_M?reJ4hQZ(2gNRX)wAo~@A!nDyR zG*-_DF5?nz5hmK%r{s*WL=v1B_fm7mgf)T;<0ro zcy#<(WG7KiRok;pCr~!&^{(<_)LX~lwbqZ(G8Pq9(x-IX9J`g7&9Z0j49SseLBrNh z=Ox(QoO9WH#VKnc>l%QZCz_}{1F_|3DV_il40(B!J=ce-2k$hzhMZgyhm~BSh~)5X zdV5+?TbB$a+Z?8$oL#n)&kzN7^zUyS$$~T0NlMBFoUo{bEeo7K-n&z=q=%v#NkA1O z=Vm&MyFv|I2j67q=#tA&aQc!Dd0ODjdi4jR+M6{U68Cc&O2rZ}VOm|Ux%UISxH{Yy(r=Qao!wV^NhEHz&>=Fx4wm(&MCv^a{8$j%QZWI#nGOy^0;vV<1N?FXe)%{_!P(1syp5oT^~KBh#3za zcWfTbk(CRoD59cEJ)PP&I#jn_w?0(NyS`hoJPDU=hp3Tbn`ia)aMc3SgS+9dErh!B z>dG4m;_Q7w2;Q7zQ|K}DqSty^iH2GX1gZrP$w^6Vd+$H3TZHXy&%IuqOhbY){xjUh zcRBMBMMZo_4%vr<0^zg7bRISVXRchtR8{x{d8j9}6}f%%Cawo)N(BqS!0RfWO7?%_ z=1yXEaSnj|(B)O(-K^GECrju&S3d}Bj)h_Di#;aLaG`by87FdrQ<3$=3)glx)#maKjGZy8sR!L_)pWva+@QV zxQi#qwY3&Scf%SPVHzPHHOnKwu(N!G)$)sHGX0>x%B~*GEgulaISb}l?qmc2XU%S~ z2QWX!XjC2+TRhQlq0-eiVz!bNVrxm&?g1x=vmiX#F#d8|OnfP0M1+d?(gVYZPa{t< ztaE0UB~=Vm=F|$+VujZNKm@c^G*I7azFYw3Q(&Mtm~3ic?z*t*uSSX@y;AI@5L+BG zhCa4mh|4WbOfmFS_f|LatZgQUVA%q6jt0<=qSay-?G)8kDg9@zC14j(m)l)ucN4_aZ(&|?OKzZD6e14 ze2lz><;)%ZSt{n*HsKe&{d4zfTwe>a<>;+W*F73rm9Cg@ifdljs1u!o43jZ}TsDT-D0-X{h#0IqR z%WDn*?&S&qxN+$z8wz&}XL?O*Q~hg+Cmwi(6aAE2y0J1|=lHF(iy-bK=b}mw!nnSt zzj))BL2dz0xl(yupBw2Uzq-sFOlr#aXx1;UJ;$k%VUstG6^fDhSd(p7ssO2p~ z8MckD8q7YqV<9VPST6NWk|cktv*C+?-RV;H`0A$2Td!MQ5Dl*4UmZKGAycvt`v3JD|ssM04wSLRCXOu zO()y?t!>xUwSZDYz(SL1q)H2`f&wBUy#!dQ5Q<1IA&U*AY5-9}5zvT0f|LXZZB+=; zk&*zRgS1ej*M$Fs)qS`R-v6!Vcn&9!WM+Od_ul!w@7{ZtCKJNiL+`t@? z4G<0edCk{CnH{b*uQ@x5(llJ?)E)+#A^uJXVoyUA}>{WisHCb+JALsczLt(OPjrfYO# z^wq`u#n@HC^~&WELDxybAo;<~hkfB6`r{ym<&7sV<_cQFbYb!H@7p2pc1<0FmX$0n zTTrqa6oj(7y$wp($h8|~F|L`zN3<+l=ztGsTCCg%O$1orA*K;~sh+-UTZQ6>fKwKL zuUKKMPBqjWmo2*{uRQN;G>PDrwVT?0UZ&&d&L=SFlC7hJ@H8X0CXKNzkhXQ>tf# z&JX^6)2H`f)wnU9c2!hEmlf5L>N7jXY86`}h)o?%?6N7w`fo&1zmcS&!W)5Ak*lfS zAe_M%5$KwSE7;a_2m>65ZO+YSy4Ke4N z?~!??66X_FpBX2Rf|2Zc)pNpe;?uL*#}p$N`*g;74Yt`2zWU190qTHsC@VRWEnS$| zInOZ_2brWz&nucsVn$2aC z_R&~#KZoe(m!llq7EPR|)FOFG$UEV1_<)GTvPS3xs7Y-ZO5DI-!3SDi{AoO(y<%GJ z+y_T3l-_kzZEu`F1%Bb?)xaN!0_{(6rqo2jtIF5(m-JWk1yY5NX{3ck!ec46Hw?6t=iIZ0}8O6dF+w)TX#Oz$?qJ|q=I_Rj zgWR+*fGA7+n`@AH`3Da8ReRu8Wu%8#^c391L|9C@+`;hYhbnv&coIqv{TV}E<_D&K zA*(BYB7f|Sl2W9C_=In#TkbX9Cjq~{IU{@5(Hf;0hm=ya*1f1FE2iBoNC7Z0GqT^AvDX+RyodTCDRs9qKvH?+e_OLC`a#qO*bXnyr9EqG^Q7Uj*kh&@eD%wgt znV)#DJpDWY%FQa{u(0n^)oM9cVj)C8tU#)|x!uszI34ZSzi%h>=xVs5msw7ac29vI zrhZ*lkFWA`LvwW>Tt>R6R9ebqd4Ue`>;3n$({AcqT7gZ>JsHg9QCN7^RyIi2X*P^ya?YbaVsSQFz9E3CyPa8XJI7 zUCX$)#Adg#fjfF8sds#MvaUMT@yFx#Tl%{B0$}}l!B7Q!0F})?{NdQnJ-z8S|4APy(!3lK(@Er*hPv^P#V1LzdB%syH!#E{#hycXfxV~Fn z{8>uCcz+E5fI33UIHfhyQ^2LEZkQ$0Jz<dC#iIt=NcVi+k9(&eX zpT?0o3PzUIr)v;_Jm_fL+KkuC(K+i%ZdPP~hvQl@BT`34@9>ks!bJI*Xb$3NV`eas zL|h_4aSziUq^Aktu3XEtTW_z=V2^`Q#?UR>K2sLvgmJ%&gPsWiN7%EDz0WkxB@;5f zDL_>se|jm271v}njVf;u&Bn9ZU$ghqiqu{;PMo8d+TW7y=6jOPs_FXG0cz|2jqort zH)GS52oxxlrga27bEo}qcTf3l>-tb{sr{k0S~dNMqf_CL&a0o;R@dg{{ZYmi>(QD{ z&e^|iCxklk_>c73M)PxNprAqp&~;dYidN3%pZ*BiX?i@9ypQjzk zz+%G--G}W~!;VP{i~OY_@VjBDe}Sa0lY1^3kDq<*`-{5p1wDSK_Uikk1b13qA|apf zaxcySiI2jK>F>pns4M$}zTwwpgzwJS$6>b_%n9G3{Cs_ z_swXI3F87TQ6Psb@amO?{P~5YGK4E8=by=dAk% z+=j~nIYz^>;Iu640vjc2s_mQa`uoG2yAXs5je4b!1qXbF8%Peddo4FrJeyKnte7Dy zvH!T-Sr_6cCUX=}9--EeN-`Q628hQ=Jw`z4vVnrVyR&;4b0zqk-`q%Mx500qazG)B z`1}R7W@K*RjfD8vT=oIJ#^xPURF^B-NlnYZh&7(xA!2t7&C;rF1(*NesEcYNo@&K> z9&KK`Zxe_$v!YS$<2j~E$NPoE#KOf6bVAM3O<0aL^M>XOe#|Q~h}2$jzG9DGubI1< zE*jc|Sak6$8~ow|3;WCMga&PPI~M|ZkW<-cEA=Xr5Kc5A1x4=e`kb0jd|6aD{Q175 zuxa$@Z!ou)k>YHv z=_p% zh;ibvfQ=q(F~NpJ7RfCqDOTA^vP?v*CM(kl3J|t5C6#hc&&K6NeDUUs-AP< zoGv^RTPIva2)F~cM)jJIKY(Ldv``*hdi*Phdww&B%eFGRR3zyV@`_*6P#}LOmAWF2 zP@~9@D{?~&^bysX^hsXGIEBUR{m{q7)n zNWA(lApN@^8drD8C-zaot%Wq~_*O@?k;j-Yl+0-wD6V>xN!uL{`10;kG~d0Kdof7R zQYR{D4O@@18T|NU`Y!LZ?+aKuVfu}EymVz&a5>f})J^C*4OMT@BI1b&Kb%8ydi4|sPs@;Xp@p*4M& z;1!u{(8pf3q#7^*x2W;rlDlQu2`aWgoZ8-IVoP>|@I*`>Rhy~cRO8$~8jOsYQ1q^c zT8BD&ht;V$$Kvt&K9drQl~Yqo1_V=MRomlkpAK5}lF)X}KhxOGy3>dVCx9Zl?tQtJ zQy*B3`IoK)cM@4Dd%m168*iKPek`>c5E1jAZ8cGxX7-uxdni)xq!ZrZM@|9RJCc&ctj#E`x`Jxlphq^72H5QmgL(92mEc2Q=G67veA?8JS} zEp&PWIF)=dXvfqfuB)xNOkUI}P0S?>$zQd1!K&N2V5vgax@j-RkJs(vUM|jDcH3qL ztGp1|?I%@;FDQ_!hpw+(VO6EzLG&pQ0c9*15j`9fr^{KNF!I*MYV6R?Y=&lTssU5} zJ)wOcg0o5sVe=7zMo_QuwkuKaB)_pYnd?9(MFN2yJ192yv4d>z42ldq4ldP&Zl4#K zV3Rcvoh&;BlfebA65pN%fvkrc_G8UgYeJL`RzNlW;)z^t7e@+}K?0CYqDCd6{0@%8T8dpV;N;@aZs+vMNC2F#!I5~b8{Aw*+) z;|8?|rI}Z6g-gBjR6+F;8@j6$aj-IusSf?-!e&tZW})P3`1tdQ&EX?dDH8dmTr9i5 z#|_mPSBvkd2M~w>ql47pWA`c7t?gsvWm|PyMS`VT{CX`VB`r-(7LH_`ZyxmoIHbO8 zg+R7Lyc}c6plEbt*cR)R^5n0m`1>C+U#sK`=3{c-ng>i*6jp-D130}M0j;39>=TQGybI(Grubg>7yzM*H_ z)hhMFB539iq8-rB3Rln~2lhV_B!R|?IV((h8?<_;ALAAS$w_5xGDVZ@+KO|zfSQU? z5Q0g-!osY(dx#qWCW9z7`BnvvCFSe1qKr>VUU<6 zTj8uVJZ{OyEqD*1;@4F{$pWtv@8%oS@4!`!^}>3To^xjIL*mFjlwqC8q~cd5nU)(EouHLY&bsL?c>9Pq+}|xpfy2Z*4H?L z+kx-z0mfIni*}Mph|=7g3omL$CB-l+#aj<2ct<37b(|qENgmMOY{d($P%6nwel3}Y zkt|@0T!vQTeq+ik0Kih=Ma9zXCz*}FNau&+qquWNF=!IFpC1Axrt3T8O@L1f%=UOd z_73ZmNn{LU<=pKK7%k+Gc8TO5d?qu+%j_8Fk%Qg0Rmo=OZ(cc$SWeJ^yoD#;HLj$; z04hh`UG0bV&g~4M1iHD3t|Hkl>1e^Ea0B~fGFZ|&7;jea+1M**O#recpIXOhmRfo; zow0UBv@4L>=2OW{Cff#si?3%6lfYq;n;XE?Q~08@W~65;K$b(Vt#|{y1->^gtFWv@ z*;$XEvo?6&A7G--Bk`iXjLdE;nXb_bl*2rW91E$xl6A(L%7 zmPzTDXHtDBZGKT$1E?pin@MX^X>>5iJgJk&V-25etPeCQ0}xx~czf=Kn7p0| zqJo1nkP5;)cnv$7n8^_)3;-0{j%hXmm}Voe ze>f%2sjfiZP%MHfAt#TXkX9OrTAzyJDEYwCKK=6qJM&qH_ye2azgw8lEo^R{cS4vK z&FK*G>$&CDV>Ri!(ihhC=*JQ=o!a_e?CgktC#__GKuJKR?xkAMSQ#SAXafRaQohrr z7>+u6VH03)07MoUq8+9)i}qS)kgk+Bi(c#o<=hg$A3|&^;hk9-r)ovQK2%ms8 z!Dw+~RzvRvqa@D1YAD4SqpB>UKrXqD;pnrau|SLP85DV-qrIVqI3zs39Xo6Q_;an} zpe1Sl0VwYQx!&IkK;@8}d#zGI(g>!hh0o1bNCZMap}W3Jx_i>9nVH8YRpXM}-Bnob zSgKt<-D+qm@F{;LS=5xpfrZvqa?mU_*FwAS>=0j7*0OCZ9m@7&U|(%OEAcKk^$I`P zd4p5`N+nK?Sn=*hQs}?GR>^#&3Paz7Y+JsqI~%RHBkn#T=hp zM{Ble)Xz*sMTU1}6)RSoETigH%GwDTpI=eqo3Lo-d}ot5y*Sg z^Fo`WTO&kOb(-#jqzCjzz+Srf>Y5b~Q>-En7iG;`0c}_e=^MoNy?s42@+)Ac_j=i* zOhrUQtU=$*Y0%8?>^=&(F|ciLwLD7l@KvB~;I&UI6h1kVFco0GHY8j2=!czqY*sx8 z;QS5Tw*4G49r47v{|&So&ArwEO$>n)l?lplGU_uYUOh)XTBmpO8za8FtsD5L=@Oa~ zQVm#fYv!U2*}8&7%K|*6Wt>1kX|(1o1XGuw`rbi#+O5wR7TXqQ$dP?}4<+Za0e=DR zij%Vji)o}Li>X9te}DhlB#bEY*A-f}>~GOlcOSPxxrl2SOM{pe@>h(|^Ac(GTN5`U z;0*N~Wf}xTzGQKLspOG!l{eg+eM zy%_O?N_wAf9xiL)Cr<0dBbAT(Ut0?}!vE;kdAzh+B_$&KvnHDz73$r$Xf=z?Zy5WT zn|UhTBrk&tnE!4Aeml`CKtOOxIK}647* zFr$dobe7^;{FU|~y6#)`Y)8;a>v{%Y`0hhf5-ZKKa#|;pEL#}UV`Ubh_Uy{B0Yi`Z z3Irt6)S9dJQ_Rj|y_-*~JBE|^-r!Ff>&uc}=P%iq%`;rpR2@`vewzp#B;%=V+Z;e8 zL7*DT2Es=8F${>yp-hY&2)Wh89YNxb!G10oQP37QsQ|Pt9sn9|W1JG50^-n$&eL$C z22i}Gey2+btrRkwoOF3&Cf!U>f8RRyPT6igwQ#Bu4`bT9zYx0aN?umxRgzzzFF}Cw zb!YCV;US@o9iFm#ioMstM)jp&~R-{Blfb&KyrrJ5x zB}tb3wTr%!8=JU3+>jfa8Qfsw?Y6TD6XoU1T~|^V5=)4^CthWT)i$VdO8?aOOJrV; z2ZsEBbknSx!&-zy+Fg{uYtg=1qhoH;J*0d2HXMD)>l;e+J&P2?b4bWh<0+4vc9x>* z3a@UHEn+VS??F7#crh2k%vJ%?qMq^}mA?d~;c)f%NPveX0)->TSxXf{&k9>9;|~!U zRkci+asM)s*IPg`Zzwh-=q~e|g;VR5PL0tVZ`X~AX1%_;+#{5cRy$?ar5?2J0B2X# zX>K(DFLsMvH#B5#V2n(*O?*6Uu-4)vYvHm|`ngJBG9*EHu^rF@w4q#Vd&xA;p(#d; zOSrVZBSyz8H|v+9l(m?LuI4HJu{f2biUKv+Ids=DjTK6!CF_5@K zLpP@;L#l4U&Od?&CW#vhCe6hhi6tqcr?`V7=~u@KmzOxMlNk-E#Ie~Nan8_dTVtj# zdYIDe3rUR28S^kuZM~oXbgwX-z<}ftP}G#oe*$lqK~6K)*yjVk;-(3Y$#r7!9hq2WE*su`6f>$9)bot*X6wsZ6UxgkcBfh~sF zC@{GhP-(bK%@y3lyyKCKWq2NZgnLH}m-F!?xmh&atX3hvN346ju$g?5@|S)3|9|kv z0@D+pqc;XCA7R26p**etA_8cQ^CwJG(XMX%FeCfJy^AJhEtL($r!+LmvAaXQ@n73; zg`1w!$PdinhbdZ>KV;ibyorqom*`r4Y3vgdcN$1W=cjEaDB4Pgr*s;)7W?>w?QX>1 zpQEpz@PZrI0BVp8`_|9zKbM^ON>JiqU|=Qd>$fpv+jxTmV73z~Is3L6{MK(#`CX-f zDeB|2x8IJ<+VYJzgH;?97P9}@Hyzx&2E2A8KuaJBRCU3GBjB`H8%WFn(|RHD?eyWT z*J7*5AT%t2r*osvQ|u{g$p;Z>7X0~a_NV{H)WmQ5=4}wrN4xa?OHOI4@7QwQfF6hK z02gE<%FrFEK})pgZrOCN13)(^ly7grzqGP5E6@F<*Xg%?yT#>f<{p&&Wcc?Zkg5A3 z3u#WMf7iZ^v>BoHM=cg1peG*vy&>3gcYT}6^(C;&_CZN%+kEJjlNpf&Z(6;YW+wCx z=KtagSTwf4u<*zKV0ex8K+wPN{CeT_e{c#^`hYH2Y>k8KP@z8>#1#8I{GyrlrGy>_`@~~@1{Tf_n7>c_PLvj%MiHc zE&pJv5sY~6ctv+9uiFE%qFORB|71^|c$*C7Mod24yY}xvZ1o*~o9=Tk%&-gFq+@LT ze#?tse|0q;z7_Znp8CInm>Je;$$vlA|Mhf&IRQg6@{=6&e_lc`Jrw~Et)^c8+eH8S zsHoQ}|cox|TJ>~s@28!q`B_1gbnW1M)rcMX|;M~V8= T?b!?e0{_%iuU*1ju)OnsEMPcu From d88e91e1db6702c7ab52486ff2743e5c0e32d727 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 22 Jun 2022 09:24:07 +0200 Subject: [PATCH 40/94] [UIMA-6473] CasToComparableText is broken - Add missing else - Fix use of wrong variable in if statement --- .../java/org/apache/uima/cas/serdes/CasToComparableText.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasToComparableText.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasToComparableText.java index 3a79a98d42..6d8a0475f7 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasToComparableText.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasToComparableText.java @@ -717,7 +717,7 @@ private Set findReachableFeatureStructures( values.stream().filter(v -> v instanceof FeatureStructure).filter(v -> !seen.contains(v)) .forEach(v -> toProcess.add((FeatureStructure) v)); } - + } else { for (Feature feature : fs.getType().getFeatures()) { if (feature.getRange().isPrimitive()) { continue; @@ -736,7 +736,7 @@ private Set findReachableFeatureStructures( List featureValues = multiValuedFeatureStructureToList( fs.getFeatureValue(feature)); - if (values != null) { + if (featureValues != null) { for (Object value : featureValues) { if (value instanceof FeatureStructure && !seen.contains(value)) { toProcess.add((FeatureStructure) value); From 3111f48a4ea50c65946028c5ba434309eb87be8c Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 22 Jun 2022 10:09:40 +0200 Subject: [PATCH 41/94] [UIMA-6474] Switch to getDataPathElements() in UimaContext - Deprecate getDataPath in UimaContext - Added getDataPathElements in UimaContext - Updated UimaContext_impl tests to use getDataPathElements instead of getDataPath --- .../java/org/apache/uima/UimaContext.java | 58 +++++++++++-------- .../uima/impl/UimaContext_ImplBase.java | 9 ++- .../uima/impl/UimaContext_implTest.java | 19 +++--- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/UimaContext.java b/uimaj-core/src/main/java/org/apache/uima/UimaContext.java index 04fdfeea49..9067a18951 100644 --- a/uimaj-core/src/main/java/org/apache/uima/UimaContext.java +++ b/uimaj-core/src/main/java/org/apache/uima/UimaContext.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.net.URI; import java.net.URL; +import java.util.List; import org.apache.uima.cas.AbstractCas; import org.apache.uima.cas.CAS; @@ -174,9 +175,9 @@ public interface UimaContext { * you may use {@link #getResourceURI(String)} or {@link #getResourceFilePath(String)}. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. * * @param aKey * the key by which the resource is identified. This key should be declared in the @@ -198,9 +199,9 @@ public interface UimaContext { * path (decoding %20 sequences to spaces) whereas {@link URL#getPath()} does not. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. * * @param aKey * the key by which the resource is identified. This key should be declared in the @@ -224,9 +225,9 @@ public interface UimaContext { * that contain spaces. * * For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. * * @param aKey * the key by which the resource is identified. This key should be declared in the @@ -246,9 +247,9 @@ public interface UimaContext { * <externalResourceDependencies> section of the descriptor. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. * * @param aKey * the key by which the resource is identified. This key should be declared in the @@ -288,9 +289,9 @@ public interface UimaContext { * you may use {@link #getResourceURI(String)} or {@link #getResourceFilePath(String)}. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. *

* This version of this method takes an array of parameters used to further identify the resource. * This can be used, for example, with resources that vary depending on the language of the @@ -323,9 +324,9 @@ public interface UimaContext { * path (decoding %20 sequences to spaces) whereas {@link URL#getPath()} does not. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. *

* This version of this method takes an array of parameters used to further identify the resource. * This can be used, for example, with resources that vary depending on the language of the @@ -360,9 +361,9 @@ public interface UimaContext { * that contain spaces. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. *

* This version of this method takes an array of parameters used to further identify the resource. * This can be used, for example, with resources that vary depending on the language of the @@ -391,9 +392,9 @@ public interface UimaContext { * <externalResourceDependencies> section of the descriptor. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPath() data path} and the class path. However, this usage is - * deprecated and support may be dropped in future versions. ALL external resource dependencies - * should be declared in the descriptor. + * up directly in the {@link #getDataPathElementsgetDataPath() data path} and the class path. + * However, this usage is deprecated and support may be dropped in future versions. ALL external + * resource dependencies should be declared in the descriptor. *

* This version of this method takes an array of parameters used to further identify the resource. * This can be used, for example, with resources that vary depending on the language of the @@ -451,9 +452,18 @@ public interface UimaContext { * the getResoureXXX methods instead. * * @return the data path + * @deprecated Use {@link #getDataPathElements()} instead. */ + @Deprecated String getDataPath(); + /** + * Gets the data path elements used to resolve relative paths. + * + * @return the data path elements + */ + List getDataPathElements(); + /** * Returns the Session object, which can be used to store data that pertains to a particular * client session. All data that must persist across requests must be stored in the Session object diff --git a/uimaj-core/src/main/java/org/apache/uima/impl/UimaContext_ImplBase.java b/uimaj-core/src/main/java/org/apache/uima/impl/UimaContext_ImplBase.java index 750c216cf0..96381685f2 100644 --- a/uimaj-core/src/main/java/org/apache/uima/impl/UimaContext_ImplBase.java +++ b/uimaj-core/src/main/java/org/apache/uima/impl/UimaContext_ImplBase.java @@ -534,14 +534,17 @@ public String getResourceFilePath(String aKey, String[] aParams) throws Resource } } - /** - * @see org.apache.uima.analysis_engine.annotator.AnnotatorContext#getDataPath() - */ + @Deprecated @Override public String getDataPath() { return getResourceManager().getDataPath(); } + @Override + public List getDataPathElements() { + return getResourceManager().getDataPathElements(); + } + protected String makeQualifiedName(String name) { return mQualifiedContextName + name; } diff --git a/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java b/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java index 4526a702c7..5635dcf50d 100644 --- a/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java @@ -19,6 +19,7 @@ package org.apache.uima.impl; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -30,6 +31,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import org.apache.uima.UIMAFramework; import org.apache.uima.UimaContext; @@ -54,8 +56,9 @@ import org.junit.jupiter.api.Test; public class UimaContext_implTest { - protected final String TEST_DATAPATH = JUnitExtension.getFile("AnnotatorContextTest").getPath() - + System.getProperty("path.separator") + JUnitExtension.getFile("ResourceTest"); + protected final List TEST_DATAPATH = asList( // + JUnitExtension.getFile("AnnotatorContextTest").getPath(), + JUnitExtension.getFile("ResourceTest").getPath()); protected final String TEST_EXTENSION_CLASSPATH = JUnitExtension .getFile("ResourceTest/spaces in dir name").getPath(); @@ -75,7 +78,7 @@ public void setUp() throws Exception { try { // configure ResourceManager to allow test components to locate their resources ResourceManager rm = UIMAFramework.newDefaultResourceManager(); - rm.setDataPath(TEST_DATAPATH); + rm.setDataPathElements(TEST_DATAPATH.toArray(new String[TEST_DATAPATH.size()])); rm.setExtensionClassPath(TEST_EXTENSION_CLASSPATH, true); // create a UimaContext with Config Params and Resources @@ -893,13 +896,9 @@ public void testGetResourceFilePathStringStringArray() throws Exception { } @Test - public void testGetDataPath() throws Exception { - try { - Assert.assertEquals(TEST_DATAPATH, mContext.getDataPath()); - Assert.assertEquals(TEST_DATAPATH, mContext2.getDataPath()); - } catch (Exception e) { - JUnitExtension.handleException(e); - } + public void testGetDataPathElements() throws Exception { + assertThat(mContext.getDataPathElements()).containsExactlyElementsOf(TEST_DATAPATH); + assertThat(mContext2.getDataPathElements()).containsExactlyElementsOf(TEST_DATAPATH); } @Test From 4d59b0fa6b9abd6f24243671d41866cf48c8d484 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 22 Jun 2022 10:12:02 +0200 Subject: [PATCH 42/94] [UIMA-6474] Switch to getDataPathElements() in UimaContext - Simplyify test code using a data path array instead of a list --- .../org/apache/uima/impl/UimaContext_implTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java b/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java index 5635dcf50d..61a14eab9e 100644 --- a/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/impl/UimaContext_implTest.java @@ -19,7 +19,6 @@ package org.apache.uima.impl; -import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -31,7 +30,6 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import org.apache.uima.UIMAFramework; import org.apache.uima.UimaContext; @@ -56,9 +54,9 @@ import org.junit.jupiter.api.Test; public class UimaContext_implTest { - protected final List TEST_DATAPATH = asList( // - JUnitExtension.getFile("AnnotatorContextTest").getPath(), - JUnitExtension.getFile("ResourceTest").getPath()); + protected final String[] TEST_DATAPATH = { // + JUnitExtension.getFile("AnnotatorContextTest").getPath(), + JUnitExtension.getFile("ResourceTest").getPath() }; protected final String TEST_EXTENSION_CLASSPATH = JUnitExtension .getFile("ResourceTest/spaces in dir name").getPath(); @@ -78,7 +76,7 @@ public void setUp() throws Exception { try { // configure ResourceManager to allow test components to locate their resources ResourceManager rm = UIMAFramework.newDefaultResourceManager(); - rm.setDataPathElements(TEST_DATAPATH.toArray(new String[TEST_DATAPATH.size()])); + rm.setDataPathElements(TEST_DATAPATH); rm.setExtensionClassPath(TEST_EXTENSION_CLASSPATH, true); // create a UimaContext with Config Params and Resources @@ -897,8 +895,8 @@ public void testGetResourceFilePathStringStringArray() throws Exception { @Test public void testGetDataPathElements() throws Exception { - assertThat(mContext.getDataPathElements()).containsExactlyElementsOf(TEST_DATAPATH); - assertThat(mContext2.getDataPathElements()).containsExactlyElementsOf(TEST_DATAPATH); + assertThat(mContext.getDataPathElements()).containsExactly(TEST_DATAPATH); + assertThat(mContext2.getDataPathElements()).containsExactly(TEST_DATAPATH); } @Test From 3679a12c8bb9378fec674f010b35cdcd9a4e763b Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 22 Jun 2022 11:35:15 +0200 Subject: [PATCH 43/94] [UIMA-6474] Switch to getDataPathElements() in UimaContext - Fix JavaDoc --- uimaj-core/src/main/java/org/apache/uima/UimaContext.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/UimaContext.java b/uimaj-core/src/main/java/org/apache/uima/UimaContext.java index 9067a18951..724e21cf97 100644 --- a/uimaj-core/src/main/java/org/apache/uima/UimaContext.java +++ b/uimaj-core/src/main/java/org/apache/uima/UimaContext.java @@ -392,9 +392,9 @@ public interface UimaContext { * <externalResourceDependencies> section of the descriptor. *

* For backwards compatibility, if the key is not declared as a resource dependency, it is looked - * up directly in the {@link #getDataPathElementsgetDataPath() data path} and the class path. - * However, this usage is deprecated and support may be dropped in future versions. ALL external - * resource dependencies should be declared in the descriptor. + * up directly in the {@link #getDataPathElements() data path} and the class path. However, this + * usage is deprecated and support may be dropped in future versions. ALL external resource + * dependencies should be declared in the descriptor. *

* This version of this method takes an array of parameters used to further identify the resource. * This can be used, for example, with resources that vary depending on the language of the From 763e262c1e83b58f46eb23871cdde137ed0d2095 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 11 Jul 2022 12:10:43 +0200 Subject: [PATCH 44/94] [UIMA-6479] PearPackagingMavenPlugin has ancient JUnit dependency - Switch from maven-project 2.0.4 to maven-core 3.0.3 (which is also used in the jcasgen plugin) - Also mark maven-core as provided in the jcasgen plugin --- PearPackagingMavenPlugin/pom.xml | 19 +++++++++++-------- jcasgen-maven-plugin/pom.xml | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/PearPackagingMavenPlugin/pom.xml b/PearPackagingMavenPlugin/pom.xml index d6e07b2da8..0ba1e63cae 100644 --- a/PearPackagingMavenPlugin/pom.xml +++ b/PearPackagingMavenPlugin/pom.xml @@ -17,7 +17,9 @@ specific language governing permissions and limitations under the License. --> - + 4.0.0 @@ -43,6 +45,7 @@ maven-plugin-api 3.1.0 + org.apache.maven.plugin-tools maven-plugin-annotations @@ -50,6 +53,13 @@ provided + + org.apache.maven + maven-core + 3.0.3 + provided + + org.apache.uima uimaj-core @@ -61,13 +71,6 @@ commons-io 2.11.0 - - - org.apache.maven - maven-project - 2.0.4 - - diff --git a/jcasgen-maven-plugin/pom.xml b/jcasgen-maven-plugin/pom.xml index 36cf7e36aa..64587ea1d5 100644 --- a/jcasgen-maven-plugin/pom.xml +++ b/jcasgen-maven-plugin/pom.xml @@ -47,6 +47,7 @@ org.apache.maven maven-core 3.0.3 + provided org.apache.maven.plugin-tools From a155fe81718bc8687284be643a51aaf070a9c366 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 11 Jul 2022 16:32:37 +0200 Subject: [PATCH 45/94] [UIMA-6480] Add tests with empty arrays to CAS de/ser-suite - Add the ability to generate random tests with empty array (although we do not activate them for all tests because the old CasCompare cannot handle them) - Add tests with empty arrays to the programmatically generated CAS suite - Switch more tests from binary file compare to content compare because the binary file compare is defied by the empty arrays - Rename test folder --- ...zationDeserialization_BINARY_TSI_Test.java | 2 +- ...ializationDeserialization_BINARY_Test.java | 2 +- ...onDeserialization_SERIALIZED_TSI_Test.java | 2 +- ...onDeserialization_XMI_1_0_PRETTY_Test.java | 28 +-- ...onDeserialization_XMI_1_1_PRETTY_Test.java | 1 + .../MultiFeatureRandomCasDataSuite.java | 12 +- .../ProgrammaticallyCreatedCasDataSuite.java | 160 +++++++++++++++++- .../MultiFeatureRandomCasGenerator.java | 69 +++++++- .../ser-ref/casWithArrays/cas.bin | Bin 0 -> 3092 bytes .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../{casWithFsList => casWithLists}/cas.bin | Bin .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../ser-ref/casWithArrays/cas.bin | Bin 0 -> 584 bytes .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../ser-ref/casWithArrays/typesystem.xml | 117 +++++++++++++ .../{casWithFsList => casWithLists}/cas.bin | Bin .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../typesystem.xml | 0 .../ser-ref/casWithArrays/cas.bin | Bin 0 -> 2856 bytes .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../ser-ref/casWithArrays/typesystem.xml | 117 +++++++++++++ .../{casWithFsList => casWithLists}/cas.bin | Bin .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../typesystem.xml | 0 .../ser-ref/casWithArrays/cas.bin | Bin 0 -> 3491 bytes .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../{casWithFsList => casWithLists}/cas.bin | Bin .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../ser-ref/casWithArrays/cas.xcas | 67 ++++++++ .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../ser-ref/casWithArrays/typesystem.xml | 117 +++++++++++++ .../{casWithFsList => casWithLists}/cas.xcas | 0 .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../typesystem.xml | 0 .../ser-ref/casWithArrays/data.xmi | 29 ++++ .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../ser-ref/casWithArrays/typesystem.xml | 117 +++++++++++++ .../{casWithFsList => casWithLists}/data.xmi | 0 .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../typesystem.xml | 0 .../ser-ref/casWithArrays/data.xmi | 29 ++++ .../casWithArrays/debug-typesystem.xml | 117 +++++++++++++ .../ser-ref/casWithArrays/debug.xmi | 29 ++++ .../ser-ref/casWithArrays/typesystem.xml | 117 +++++++++++++ .../{casWithFsList => casWithLists}/data.xmi | 0 .../debug-typesystem.xml | 0 .../{casWithFsList => casWithLists}/debug.xmi | 0 .../typesystem.xml | 0 60 files changed, 1965 insertions(+), 43 deletions(-) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/cas.bin create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/debug.xmi rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/{casWithFsList => casWithLists}/cas.bin (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/cas.bin create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/typesystem.xml rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/{casWithFsList => casWithLists}/cas.bin (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/{casWithFsList => casWithLists}/typesystem.xml (100%) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/cas.bin create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/typesystem.xml rename uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/cas.bin (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/typesystem.xml (100%) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/cas.bin create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug.xmi rename uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/cas.bin (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/cas.xcas create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/typesystem.xml rename uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/{casWithFsList => casWithLists}/cas.xcas (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/{casWithFsList => casWithLists}/typesystem.xml (100%) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/data.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/data.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/typesystem.xml (100%) create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/data.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug.xmi create mode 100644 uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/data.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/debug-typesystem.xml (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/debug.xmi (100%) rename uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/{casWithFsList => casWithLists}/typesystem.xml (100%) diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_TSI_Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_TSI_Test.java index ecd7e41243..4cbe8f0de5 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_TSI_Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_TSI_Test.java @@ -66,7 +66,7 @@ private static List oneWayDesSerScenarios() throws Exception } private static List roundTripDesSerScenarios() throws Exception { - return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingFileContents(desSerCycles, + return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingCasContents(desSerCycles, CAS_FILE_NAME); } diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_Test.java index 6c259c2f3b..94ab5955df 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_BINARY_Test.java @@ -62,7 +62,7 @@ private static List oneWayDesSerScenarios() throws Exception } private static List roundTripDesSerScenarios() throws Exception { - return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingFileContents(desSerCycles, + return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingCasContents(desSerCycles, CAS_FILE_NAME); } diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_SERIALIZED_TSI_Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_SERIALIZED_TSI_Test.java index 6e2171d04b..677aa314f9 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_SERIALIZED_TSI_Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_SERIALIZED_TSI_Test.java @@ -65,7 +65,7 @@ private static List oneWayDesSerScenarios() throws Exception } private static List roundTripDesSerScenarios() throws Exception { - return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingFileContents(desSerCycles, + return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingCasContents(desSerCycles, CAS_FILE_NAME); } diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_0_PRETTY_Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_0_PRETTY_Test.java index 2200824c2e..91be87f737 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_0_PRETTY_Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_0_PRETTY_Test.java @@ -77,36 +77,10 @@ private static List serDesScenarios() { return SerDesCasIOTestUtils.programmaticSerDesScenarios(serDesCycles); } - // private static List desSerScenarios() { - // TestType type; - // - // Class testClass = CasSerializationDeserialization_XMI_1_0_PRETTY_Test.class; - // - // List scenarios = new ArrayList<>(); - // DesSerTestScenario.builder() // - // .withTitle("multipleEmptyFSArrays") // - // .withSourceCasFile(Paths.get( - // "src/test/resources/XmiFileDataSuite/tsv3-testStackedComplexSlotFeatureWithoutSlotFillers/data.xmi")) - // // - // .withReferenceCasFile(DES_REF.getReferenceFolder(testClass) - // .resolve("tsv3-testStackedComplexSlotFeatureWithoutSlotFillers") - // .resolve("data.xmi")) // - // .withTargetBasePath(DES_REF.getTargetFolder(testClass) - // .resolve("tsv3-testStackedComplexSlotFeatureWithoutSlotFillers")) // - // .withCycle((a, b) -> { - // CAS buffer = createCasMaybeWithTypesystem(a); - // des(buffer, a, DEFAULT); - // Type linkHostType = buffer.getTypeSystem().getType("webanno.custom.ComplexLinkHost"); - // List linkHosts = buffer. select(linkHostType).asList(); - // FSArray array1 = (FSArray) linkHosts.get(0) - // .getFeatureValue(linkHostType.getFeatureByBaseName("links")); - // }); // - // return scenarios; - // } - private static List randomSerDesScenarios() { return SerDesCasIOTestUtils.serDesScenarios(serDesCycles, MultiFeatureRandomCasDataSuite.builder() // + .withEmptyArrays(false) // .withIterations(RANDOM_CAS_ITERATIONS) // .withStringArrayMode(NULL_STRINGS_AS_EMPTY) // .build(), diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_1_PRETTY_Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_1_PRETTY_Test.java index c4e009b9b6..b9b5078de1 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_1_PRETTY_Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_XMI_1_1_PRETTY_Test.java @@ -80,6 +80,7 @@ private static List serDesScenarios() { private static List randomSerDesScenarios() { return SerDesCasIOTestUtils.serDesScenarios(serDesCycles, MultiFeatureRandomCasDataSuite.builder() // + .withEmptyArrays(false) // .withIterations(RANDOM_CAS_ITERATIONS) // .withStringArrayMode(NULL_STRINGS_AS_EMPTY) // .build(), diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/MultiFeatureRandomCasDataSuite.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/MultiFeatureRandomCasDataSuite.java index e2dccb41af..1598dbaae5 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/MultiFeatureRandomCasDataSuite.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/MultiFeatureRandomCasDataSuite.java @@ -34,12 +34,14 @@ public class MultiFeatureRandomCasDataSuite extends AbstractCollection iterator() { for (int n = 0; n < iterations; n++) { MultiFeatureRandomCasGenerator randomizer = MultiFeatureRandomCasGenerator.builder() // - .withStringArrayMode(stringArrayMode).withSize((n + 1) * sizeFactor) // + .withStringArrayMode(stringArrayMode) // + .withSize((n + 1) * sizeFactor) // + .withEmptyArrays(emptyArrays) // .build(); CasConfiguration cfg = new CasConfiguration(randomizer); @@ -84,6 +88,7 @@ public static final class Builder { private int iterations = 10; private int sizeFactor = 10; private StringArrayMode stringArrayMode = ALLOW_NULL_AND_EMPTY_STRINGS; + private boolean emtpyArrays = true; private Builder() { } @@ -103,6 +108,11 @@ public Builder withIterations(int aIterations) { return this; } + public Builder withEmptyArrays(boolean aFlag) { + emtpyArrays = aFlag; + return this; + } + public MultiFeatureRandomCasDataSuite build() { return new MultiFeatureRandomCasDataSuite(this); } diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/ProgrammaticallyCreatedCasDataSuite.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/ProgrammaticallyCreatedCasDataSuite.java index 62ef2b7556..ed237ebc54 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/ProgrammaticallyCreatedCasDataSuite.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/datasuites/ProgrammaticallyCreatedCasDataSuite.java @@ -26,11 +26,15 @@ import static java.util.Arrays.asList; import static org.apache.uima.cas.CAS.TYPE_NAME_DOUBLE; import static org.apache.uima.cas.CAS.TYPE_NAME_FLOAT; +import static org.apache.uima.cas.CAS.TYPE_NAME_FLOAT_ARRAY; import static org.apache.uima.cas.CAS.TYPE_NAME_FLOAT_LIST; +import static org.apache.uima.cas.CAS.TYPE_NAME_FS_ARRAY; import static org.apache.uima.cas.CAS.TYPE_NAME_FS_LIST; import static org.apache.uima.cas.CAS.TYPE_NAME_INTEGER; +import static org.apache.uima.cas.CAS.TYPE_NAME_INTEGER_ARRAY; import static org.apache.uima.cas.CAS.TYPE_NAME_INTEGER_LIST; import static org.apache.uima.cas.CAS.TYPE_NAME_STRING; +import static org.apache.uima.cas.CAS.TYPE_NAME_STRING_ARRAY; import static org.apache.uima.cas.CAS.TYPE_NAME_STRING_LIST; import static org.apache.uima.cas.CAS.TYPE_NAME_TOP; import static org.apache.uima.util.CasCreationUtils.createCas; @@ -41,11 +45,14 @@ import java.util.List; import org.apache.uima.UIMAFramework; +import org.apache.uima.cas.ArrayFS; import org.apache.uima.cas.ByteArrayFS; import org.apache.uima.cas.CAS; import org.apache.uima.cas.DoubleArrayFS; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.FloatArrayFS; +import org.apache.uima.cas.IntArrayFS; +import org.apache.uima.cas.StringArrayFS; import org.apache.uima.cas.Type; import org.apache.uima.cas.serdes.transitions.CasSourceTargetConfiguration; import org.apache.uima.cas.text.AnnotationFS; @@ -120,8 +127,14 @@ private ProgrammaticallyCreatedCasDataSuite(Builder builder) { typeSystemWithFloatingPointSpecialValues(), null, null, null)) // .build(), CasSourceTargetConfiguration.builder() // - .withTitle("casWithFsList") // - .withSourceCasSupplier(ProgrammaticallyCreatedCasDataSuite::casWithFsList) + .withTitle("casWithLists") // + .withSourceCasSupplier(ProgrammaticallyCreatedCasDataSuite::casWithListFeatures) + .withTargetCasSupplier(CasCreationUtils::createCas) // + .build(), + CasSourceTargetConfiguration.builder() // + .withTitle("casWithArrays") // + .withSourceCasSupplier( + ProgrammaticallyCreatedCasDataSuite::casWithArrayFeatures) .withTargetCasSupplier(CasCreationUtils::createCas) // .build()); } @@ -247,7 +260,7 @@ public static TypeSystemDescription typeSystemWithFloatingPointSpecialValues() t return tsd; } - public static TypeSystemDescription typeSystemWithFsListFeature() throws Exception { + public static TypeSystemDescription typeSystemWithListFeatures() throws Exception { TypeSystemDescription tsd = UIMAFramework.getResourceSpecifierFactory() .createTypeSystemDescription(); @@ -279,6 +292,39 @@ public static TypeSystemDescription typeSystemWithFsListFeature() throws Excepti return tsd; } + public static TypeSystemDescription typeSystemWithArrayFeatures() throws Exception { + TypeSystemDescription tsd = UIMAFramework.getResourceSpecifierFactory() + .createTypeSystemDescription(); + + TypeDescription fsArrayHolder = tsd.addType("FsArrayHolder", null, TYPE_NAME_TOP); + fsArrayHolder.addFeature("fsArray", null, TYPE_NAME_FS_ARRAY, TYPE_NAME_TOP, false); + + TypeDescription fsArrayHolderMr = tsd.addType("FsArrayHolderMR", null, TYPE_NAME_TOP); + fsArrayHolderMr.addFeature("fsArray", null, TYPE_NAME_FS_ARRAY, TYPE_NAME_TOP, true); + + TypeDescription intArrayHolder = tsd.addType("IntArrayHolder", null, TYPE_NAME_TOP); + intArrayHolder.addFeature("intArray", null, TYPE_NAME_INTEGER_ARRAY, TYPE_NAME_INTEGER, false); + + TypeDescription intArrayHolderMr = tsd.addType("IntArrayHolderMR", null, TYPE_NAME_TOP); + intArrayHolderMr.addFeature("intArray", null, TYPE_NAME_INTEGER_ARRAY, TYPE_NAME_INTEGER, true); + + TypeDescription floatArrayHolder = tsd.addType("FloatArrayHolder", null, TYPE_NAME_TOP); + floatArrayHolder.addFeature("floatArray", null, TYPE_NAME_FLOAT_ARRAY, TYPE_NAME_FLOAT, false); + + TypeDescription floatArrayHolderMr = tsd.addType("FloatArrayHolderMR", null, TYPE_NAME_TOP); + floatArrayHolderMr.addFeature("floatArray", null, TYPE_NAME_FLOAT_ARRAY, TYPE_NAME_FLOAT, true); + + TypeDescription stringArrayHolder = tsd.addType("StringArrayHolder", null, TYPE_NAME_TOP); + stringArrayHolder.addFeature("stringArray", null, TYPE_NAME_STRING_ARRAY, TYPE_NAME_STRING, + false); + + TypeDescription stringArrayHolderMr = tsd.addType("StringArrayHolderMR", null, TYPE_NAME_TOP); + stringArrayHolderMr.addFeature("stringArray", null, TYPE_NAME_STRING_ARRAY, TYPE_NAME_STRING, + true); + + return tsd; + } + public static CAS casWithFloatingPointSpecialValues() throws Exception { CAS cas = createCas(typeSystemWithFloatingPointSpecialValues(), null, null, null); @@ -315,8 +361,8 @@ public static CAS casWithFloatingPointSpecialValues() throws Exception { return cas; } - public static CAS casWithFsList() throws Exception { - CAS cas = createCas(typeSystemWithFsListFeature(), null, null, null); + public static CAS casWithListFeatures() throws Exception { + CAS cas = createCas(typeSystemWithListFeatures(), null, null, null); AnnotationFS a1 = cas.createAnnotation(cas.getAnnotationType(), 0, 1); AnnotationFS a2 = cas.createAnnotation(cas.getAnnotationType(), 1, 2); @@ -377,6 +423,110 @@ public static CAS casWithFsList() throws Exception { return cas; } + public static CAS casWithArrayFeatures() throws Exception { + CAS cas = createCas(typeSystemWithArrayFeatures(), null, null, null); + + AnnotationFS a1 = cas.createAnnotation(cas.getAnnotationType(), 0, 1); + AnnotationFS a2 = cas.createAnnotation(cas.getAnnotationType(), 1, 2); + FeatureStructure[] fsArrayValue = { a1, a2 }; + + ArrayFS arrayFs = cas.createArrayFS(fsArrayValue.length); + arrayFs.copyFromArray(fsArrayValue, 0, 0, fsArrayValue.length); + cas.addFsToIndexes(arrayFs); + + Type fsArrayHolderType = cas.getTypeSystem().getType("FsArrayHolder"); + FeatureStructure fsArrayHolder = cas.createFS(fsArrayHolderType); + ArrayFS arrayFs1 = cas.createArrayFS(fsArrayValue.length); + arrayFs1.copyFromArray(fsArrayValue, 0, 0, fsArrayValue.length); + fsArrayHolder.setFeatureValue(fsArrayHolderType.getFeatureByBaseName("fsArray"), arrayFs1); + cas.addFsToIndexes(fsArrayHolder); + + FeatureStructure fsArrayHolderEmpty = cas.createFS(fsArrayHolderType); + fsArrayHolderEmpty.setFeatureValue(fsArrayHolderType.getFeatureByBaseName("fsArray"), + cas.emptyFSArray()); + cas.addFsToIndexes(fsArrayHolder); + + Type fsArrayHolderMrType = cas.getTypeSystem().getType("FsArrayHolderMR"); + FeatureStructure fsArrayHolderMr = cas.createFS(fsArrayHolderMrType); + ArrayFS arrayFsMr = cas.createArrayFS(fsArrayValue.length); + arrayFsMr.copyFromArray(fsArrayValue, 0, 0, fsArrayValue.length); + fsArrayHolderMr.setFeatureValue(fsArrayHolderMrType.getFeatureByBaseName("fsArray"), arrayFsMr); + cas.addFsToIndexes(fsArrayHolderMr); + + int[] intArrayValue = { 1, 2 }; + + Type intArrayHolderType = cas.getTypeSystem().getType("IntArrayHolder"); + FeatureStructure intArrayHolder = cas.createFS(intArrayHolderType); + IntArrayFS intArray = cas.createIntArrayFS(intArrayValue.length); + intArray.copyFromArray(intArrayValue, 0, 0, intArrayValue.length); + intArrayHolder.setFeatureValue(intArrayHolderType.getFeatureByBaseName("intArray"), intArray); + cas.addFsToIndexes(intArrayHolder); + + FeatureStructure intArrayHolderEmpty = cas.createFS(intArrayHolderType); + intArrayHolderEmpty.setFeatureValue(intArrayHolderType.getFeatureByBaseName("intArray"), + cas.emptyIntegerArray()); + cas.addFsToIndexes(intArrayHolderEmpty); + + Type intArrayHolderMrType = cas.getTypeSystem().getType("IntArrayHolderMR"); + FeatureStructure intArrayHolderMr = cas.createFS(intArrayHolderMrType); + IntArrayFS intArrayMr = cas.createIntArrayFS(intArrayValue.length); + intArrayMr.copyFromArray(intArrayValue, 0, 0, intArrayValue.length); + intArrayHolderMr.setFeatureValue(intArrayHolderMrType.getFeatureByBaseName("intArray"), + intArrayMr); + cas.addFsToIndexes(intArrayHolderMr); + + float[] floatArrayValue = { -1.0f, 0.0f, 1.0f, NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY, + MIN_VALUE, MAX_VALUE }; + + Type floatArrayHolderType = cas.getTypeSystem().getType("FloatArrayHolder"); + FeatureStructure floatArrayHolder = cas.createFS(floatArrayHolderType); + FloatArrayFS floatArray = cas.createFloatArrayFS(floatArrayValue.length); + floatArray.copyFromArray(floatArrayValue, 0, 0, floatArrayValue.length); + floatArrayHolder.setFeatureValue(floatArrayHolderType.getFeatureByBaseName("floatArray"), + floatArray); + cas.addFsToIndexes(floatArrayHolder); + + FeatureStructure floatArrayHolderEmpty = cas.createFS(floatArrayHolderType); + floatArrayHolderEmpty.setFeatureValue(floatArrayHolderType.getFeatureByBaseName("floatArray"), + cas.emptyFloatArray()); + cas.addFsToIndexes(floatArrayHolderEmpty); + + Type floatArrayHolderMrType = cas.getTypeSystem().getType("FloatArrayHolderMR"); + FeatureStructure floatArrayHolderMr = cas.createFS(floatArrayHolderMrType); + FloatArrayFS floatArrayMr = cas.createFloatArrayFS(floatArrayValue.length); + floatArrayMr.copyFromArray(floatArrayValue, 0, 0, floatArrayValue.length); + floatArrayHolderMr.setFeatureValue(floatArrayHolderMrType.getFeatureByBaseName("floatArray"), + floatArrayMr); + cas.addFsToIndexes(floatArrayHolderMr); + + String[] stringArrayValue = { "blah", "blub" }; + + // We do not push null or the empty string here because different formats handle it differently + // and we have tests for that in other places + Type stringArrayHolderType = cas.getTypeSystem().getType("StringArrayHolder"); + FeatureStructure stringArrayHolder = cas.createFS(stringArrayHolderType); + StringArrayFS stringArray = cas.createStringArrayFS(stringArrayValue.length); + stringArray.copyFromArray(stringArrayValue, 0, 0, stringArrayValue.length); + stringArrayHolder.setFeatureValue(stringArrayHolderType.getFeatureByBaseName("stringArray"), + stringArray); + cas.addFsToIndexes(stringArrayHolder); + + FeatureStructure stringArrayHolderEmpty = cas.createFS(stringArrayHolderType); + stringArrayHolderEmpty.setFeatureValue( + stringArrayHolderType.getFeatureByBaseName("stringArray"), cas.emptyStringArray()); + cas.addFsToIndexes(stringArrayHolderEmpty); + + Type stringArrayHolderMrType = cas.getTypeSystem().getType("StringArrayHolderMR"); + FeatureStructure stringArrayHolderMr = cas.createFS(stringArrayHolderMrType); + StringArrayFS stringArrayMr = cas.createStringArrayFS(stringArrayValue.length); + stringArrayMr.copyFromArray(stringArrayValue, 0, 0, stringArrayValue.length); + stringArrayHolderMr.setFeatureValue(stringArrayHolderMrType.getFeatureByBaseName("stringArray"), + stringArrayMr); + cas.addFsToIndexes(stringArrayHolderMr); + + return cas; + } + private static void createAnnotatedText(CAS aCas, StringBuilder aBuffer, String aText, String... aSuffix) { int begin = aBuffer.length(); diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/generators/MultiFeatureRandomCasGenerator.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/generators/MultiFeatureRandomCasGenerator.java index 5e4709544b..7bff362ba4 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/generators/MultiFeatureRandomCasGenerator.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/generators/MultiFeatureRandomCasGenerator.java @@ -104,6 +104,7 @@ public class MultiFeatureRandomCasGenerator implements CasGenerator { private final Random rnd; private final int size; private final StringArrayMode stringArrayMode; + private final boolean emptyArrays; // akof = all kinds of features private Type akof; @@ -145,6 +146,7 @@ private MultiFeatureRandomCasGenerator(Builder builder) { rnd = builder.randomGenerator; size = builder.size; stringArrayMode = builder.stringArrayMode; + emptyArrays = builder.emptyArrays; aint = includeUid ? new AtomicInteger(0) : null; } @@ -310,66 +312,113 @@ private String randomString(Random r) { } private StringArrayFS randomStringA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + + if (length == 0) { + return maybeKeep(cas.emptyStringArray()); + } + StringArrayFS fs = maybeKeep(cas.createStringArrayFS(length)); for (int i = 0; i < length; i++) { fs.set(i, randomString(r)); } + return fs; } private IntArrayFS randomIntA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + + if (length == 0) { + return maybeKeep(cas.emptyIntegerArray()); + } + IntArrayFS fs = maybeKeep(cas.createIntArrayFS(length)); for (int i = 0; i < length; i++) { fs.set(i, r.nextInt(101) - 50); } + return fs; } private ByteArrayFS randomByteA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + ; + + if (length == 0) { + return maybeKeep(cas.emptyByteArray()); + } + ByteArrayFS fs = maybeKeep(cas.createByteArrayFS(length)); for (int i = 0; i < length; i++) { int bvidx = r.nextInt(BYTE_VALUES.length); fs.set(i, BYTE_VALUES[bvidx]); } + return fs; } private LongArrayFS randomLongA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + ; + + if (length == 0) { + return maybeKeep(cas.emptyLongArray()); + } + LongArrayFS fs = maybeKeep(cas.createLongArrayFS(length)); for (int i = 0; i < length; i++) { fs.set(i, LONG_VALUES[r.nextInt(LONG_VALUES.length)]); } + return fs; } private ShortArrayFS randomShortA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + ; + + if (length == 0) { + return maybeKeep(cas.emptyShortArray()); + } + ShortArrayFS fs = maybeKeep(cas.createShortArrayFS(length)); for (int i = 0; i < length; i++) { fs.set(i, SHORT_VALUES[r.nextInt(SHORT_VALUES.length)]); } + return fs; } private DoubleArrayFS randomDoubleA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + ; + + if (length == 0) { + return maybeKeep(cas.emptyDoubleArray()); + } + DoubleArrayFS fs = maybeKeep(cas.createDoubleArrayFS(length)); for (int i = 0; i < length; i++) { fs.set(i, DOUBLE_VALUES[r.nextInt(DOUBLE_VALUES.length)]); } + return fs; } private FloatArrayFS randomFloatA(Random r) { - int length = r.nextInt(2) + 1; + int length = r.nextInt(3) + (emptyArrays ? 0 : 1); + ; + + if (length == 0) { + return maybeKeep(cas.emptyFloatArray()); + } + FloatArrayFS fs = maybeKeep(cas.createFloatArrayFS(length)); for (int i = 0; i < length; i++) { fs.set(i, FLOAT_VALUES[r.nextInt(FLOAT_VALUES.length)]); } + return fs; } @@ -401,6 +450,7 @@ public static final class Builder { private Random randomGenerator; private int size; private StringArrayMode stringArrayMode = ALLOW_NULL_AND_EMPTY_STRINGS; + private boolean emptyArrays; private Builder() { } @@ -430,6 +480,11 @@ public Builder withStringArrayMode(StringArrayMode aStringArrayMode) { return this; } + public Builder withEmptyArrays(boolean aFlag) { + emptyArrays = aFlag; + return this; + } + public MultiFeatureRandomCasGenerator build() { if (randomGenerator == null) { randomGenerator = new Random(); diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/cas.bin new file mode 100644 index 0000000000000000000000000000000000000000..c708cf9bcc7c1226722d3466575896e506c06f4d GIT binary patch literal 3092 zcma)8U2hvj6uowuHea>#(KJbuLer1X7V08ii-4pdU@1;YoJL4Sf{C+s7TLRIJzE-( zNPh+Y0Eq{9;gJ{k4g3IJ5lFo89?qHFnO!?YVx*I~d*;raJNI7S$uZ^7Y=5qvsfQgEv>(=WQ~d(uF<=$A1xy1R zGeE&e_~SG`vP?Q(#ykm7lQL(5R!TW}1Tx1QU@cR&zFdWT1>j!F^onB@usW3Ud|u{0 z;=gomrfZnYEv-%7*vhvdTbp+vUjjJR0Lrxg8gLQdxC>Awe-B_3Iqn0L$-fSa0~~Jv zlnY2pT9g$QWd)_hqWtlNm)B;sb>m_!70L{I=xJO+~xHk2({9F7#PMC z9Ft=bG{AsF80mybn6sJ{Y9>9PaypojJVx=I2iGP5mNY?`WlT_J=@OJ#uC`?JHYw+A zTG{H{#5&8)e!p~fH+p~~m~!oOfA@)&Y4=$T(2=}IOUY4NOp%tdBW#*y9b?k5q0shn zrnc&aM!R%+##GAAJ2pKt<*ztCIVYuO9KG%Lb#hkb(pH_UmTdF;-JU+N^n%;G69xk- z*&U2;iIq$}(PaRVm22k>WsBM2>5Y;-OKy*`Hn6th)~sU#%UR@-SR@7)-6mr&zqIU@ ztiAkdmgbEx?05>l$jffS#)(Gyvb5Ka!w3=06t=^loiBsUFh1;HOP0vgYMQYuv^1TP zxf{{`IaMB#l36&DlTtc!h(C5MS+cSpd{Q2X0nL9JvL!7^%niL6Hsh{`4&zz{3OFm$ z55o>#KrOSwRBaD|*-9FfRVojBQ=^1j8mFzw^dLc)&I2>ZizfIVUnxDT*n@)=qNUIF+F-2wQ#@Yz}b*k@*eYXG0C z6@Y!K4Dgxalgv)K1l$GKIoW$&1^6tnm$B!40&vhbt`oz<_Al~Wx8Ia`2G8S6zj;sk z%li-W^n-p5^EM9LPdnBwdF~<4!PqdK!+MO(TL9xQ_R9lXPg0y!s+SR z8D{Fg15lr14cGww?|$ZC2VflOFTq@s-v`KZ(ASRvtH&HLZ!7YtR3#8!G@zs-2bewi zQVt<2IW}{Qzr){2&S1g}#+smA=9@F~%9*ufdB)R%`qZT!YlnBg0Wh|20&fHF0o%YH MZ~$;G$M7uw0 + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithFsList/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithLists/cas.bin similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithFsList/cas.bin rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithLists/cas.bin diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_TSI_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/cas.bin new file mode 100644 index 0000000000000000000000000000000000000000..7494b7a903d7411cb32c545c5d756decd788175f GIT binary patch literal 584 zcma)&O-lk%7=_Phno$cEA`vdE=u2IM>(F#JU@fAgMGyu-g0w1Hj{i*m+4LNl3vy}E zfoIOWXU=<>xlifcNJ%M?^a9o~cyD5z5`^3y_Fk8uT6hgVfD33soL`c){>ZP$PQdd% zFP!V#GtR9J^dRn?k@aEM?^a8mXtq+iSRiTbRHDOu@5O?D_?o$tHXN literal 0 HcmV?d00001 diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug-typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug-typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithArrays/typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/cas.bin similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/cas.bin rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/cas.bin diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithFsList/typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_BINARY_Test/ser-ref/casWithLists/typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/cas.bin new file mode 100644 index 0000000000000000000000000000000000000000..e266d449a9523480fd976c15a110a7037175f0e5 GIT binary patch literal 2856 zcmZ`*&2Jk;6d&736DN+H@9zR>X-P`sN?e14oQ8l=oP;<@55DYpcl-hN?y??N4M-d~ z^}q=P{{a#QxFAma0Z6ntRJ4d23Lz>2i5pVIsl4Cp?(CYBk$&E{zxOe3X5PN>L9tX| ziDZT`miX!~*5C2iisRMu+~sCNM~zVJ$^@h{gt z|K;x_8!fU69jEJ=qR57&G0qhQvoP0{xqm0O9s0Xx-E@yp$+q?H`JV)p`On@b1JOM<>#^e;q7!!mrGUPCqX_6-i@P&-5 zFqR0R4dgfXFm0cR;dUwx}EOt>`FGOUyC+%B;iSx)zl`A zNV1$J!ebuSj5>~WPHit1YO}0pYM0thg$mdy%?5J@{G{gnc>;P&(_77s^yi9F+AM>W zEOLIm?aHH&p3%yeC(1%hZTMBetGx-B>pr+D#`pk zSM-KscH4qFjBXWFz)_LD>9ptulx+OJRB4YkX47v}p;4~q9Tr(SOO&_nRwX^DVdf~ynPA+8bhhl>RCh*`ol0y-wHp#{Qo z1YAQ`2)JHwZOstSXT}Nh1YB2(1oW*O0oN3+WOULw!ZHD!6TRno0y<3%|u0kdMJc}#(q6z0a7234CUK}A=_pjC>P2l*^w6O;-&pai6hSQ+Gv z^-sePLHn_5%EqkHFiwpV_6ai$er9}TSOr2D`{elk^&hs5)AzSl2PmRtoh8Wd EUj=uQX#fBK literal 0 HcmV?d00001 diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithArrays/typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/cas.bin similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/cas.bin rename to uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/cas.bin diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithFsList/typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test/ser-ref/casWithLists/typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/cas.bin new file mode 100644 index 0000000000000000000000000000000000000000..4b2ceac5c4075d59d7d263b48988cc99526321f0 GIT binary patch literal 3491 zcma)9TW=dh6rMPZo2#8mOD}05EwrRJ8}S+hG!3Dy?6kxoLNYB(oUvnM@0#^&NkF2N zct=7=`~if-Ly-W9hw=h{fEQko5HARUgphy-;H7-u?9S{uDHS7q-m~91bLMi+o*Ccy zRSfk4QSgIiL3U+*OBKRaM;7X`S7>#*?ZTyt)k{7ErBzi0E!l3pse&87&llTwZ!Bd* zrYuHaTWJQ+YH_X%N5#ldk&cQ`7U`%6N0C+RW1%dvP?~P@5A2qVyRhBGWY0WkvVCJz z2B$w>_~83LGh(tNvOPZx>Z&BhwBKFZ>8eZqrmBg29m|t})P7L%Hr2KknOdnP#uB>s zx_Da*)x=0cNxh`%ZA*-k2m`euJF2I}Os)KyyeW%q={1X09kjgWLQUjiqpOWZPifnA zw8gPZM|#iJ#H3-+2R)@$&7FAEoCoh~zL{G^c4PKn&-kx~8yYKFm+eqp^R4rly-K6P zD7ikB?U1LFlDCBbYw6XMT`=kN97jl84K`I^EVjEMZehS(t9<$D>6^cN{!vBZ7D46^lk3i5t{?KD7{{vQXj0NXr3nfw`m zyU2DHpiKT8Faofh2Ph99EOAm6n3M&i7L)RmZ`XhN`S@GUV?HKMvt2FrY1wMyv8CiD zqm|=N{(h1c`+I&vu7n-UZ>k|nOIi$fTF6plhZZB`E(U?z(PETxG-}-K#nlo1=WD53zGoPha14$KP#*&l+sH|nO?O_CL`|d%G>#iXlEx6;)1Yn?U`i8| znZ^WVrY=F5>1tCp?UQoar-*REdEV$!{qJX9nW_?)Ab z86qw6j<8{#c8m$fqD0wCxmvCo8s*a28CNlT(6RBDF@M1E(Ks+#&r=ziwDJ@sY zYLRq)uG7^!mOkV==LM~N~SJYG@M=ZNcLy!GjhIh~zY zpE}vOXfGm%hg~P*Fs+((D(f$;O~SnB`)wuhMNYU5i#rVo>(IW;zX) z{BQ%e1(5_Y_8Lbl*;=}e$<&JIe~&2#iOFO;qmg1dnGipAEs|g*AAFP^kps;ePNLEx z+H*rM`Sq})P+?rDKmsR8df9K|1k_@BH&t21#w~698)ok4_$kJVsa_jsvU_hk>&Is~nG^S>R!S z$IvN&#|w|GLjdc{G;kE)adiw}-O2+zrg$W?k{$u(0UmX%J&yo9mRQTiaF09vpnF_$ z>3i?`-4DO}=H0(DVt-9cY#?baE7^_1o~bR?csQ6^&N9t=8qTmt9~0vwDoV>Gsb$Pf zw2@MMj;`=_#O&*1tGEjG%(1y9k=N{<-R_$E&f=Xv4*iuKUi$%yHRtF+au#q8()E@x zAjh?H-?+zf0QdX};3?o)pbV@6>n^e{pwS`mt4>6m9G~Wk!Ng;giwjOc+&W z$!?y}Vl;R2He1-Aeym^e>_eW7t2qzswqpi82{2oRzq*ZIv}bM$aqDX#?(qqr4cxkQ z?;f7Ce;S}Y8+U6F_`m&`tt$Ytjq@e=MUY-F9Ft$nL6Zlo}=9c7y%mvh%~}Q zl{eli+jINAnEot$9|Oc0V3e`C`rA8&?2p$!{U@b%=WUkf?JFg(rSXSoy`|p3wP>R) Ox6C8lV4|69Yy1mg0|^NL literal 0 HcmV?d00001 diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug-typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithFsList/cas.bin b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithLists/cas.bin similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithFsList/cas.bin rename to uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithLists/cas.bin diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_SERIALIZED_TSI_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/cas.xcas b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/cas.xcas new file mode 100644 index 0000000000..bbaa5dc963 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/cas.xcas @@ -0,0 +1,67 @@ + + + + 2 + 3 + + + + + + + + + + + + + + blah + blub + + + + blah + blub + + + -1.0 + 0.0 + 1.0 + NaN + -Infinity + Infinity + 1.4E-45 + 3.4028235E38 + + + + -1.0 + 0.0 + 1.0 + NaN + -Infinity + Infinity + 1.4E-45 + 3.4028235E38 + + + 1 + 2 + + + 1 + 2 + + + + 2 + 3 + + + 2 + 3 + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug-typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug-typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithArrays/typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/cas.xcas b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/cas.xcas similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/cas.xcas rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/cas.xcas diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithFsList/typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XCAS_Test/ser-ref/casWithLists/typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/data.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/data.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/data.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/data.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/data.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/data.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/data.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithFsList/typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_0_PRETTY_Test/ser-ref/casWithLists/typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/data.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/data.xmi new file mode 100644 index 0000000000..e778da0c69 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/data.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug-typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug.xmi new file mode 100644 index 0000000000..72ee1cd1c5 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/debug.xmi @@ -0,0 +1,29 @@ + + + + + + + + + + + + + blah + blub + + + + + + + + + + + blah + blub + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml new file mode 100644 index 0000000000..9b89fba962 --- /dev/null +++ b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithArrays/typesystem.xml @@ -0,0 +1,117 @@ + + + + + uima.tcas.DocumentAnnotation + + uima.tcas.Annotation + + + language + + uima.cas.String + + + + + FloatArrayHolder + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + + + + + FloatArrayHolderMR + + uima.cas.TOP + + + floatArray + + uima.cas.FloatArray + true + + + + + FsArrayHolder + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + + + + + FsArrayHolderMR + + uima.cas.TOP + + + fsArray + + uima.cas.FSArray + true + + + + + IntArrayHolder + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + + + + + IntArrayHolderMR + + uima.cas.TOP + + + intArray + + uima.cas.IntegerArray + true + + + + + StringArrayHolder + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + + + + + StringArrayHolderMR + + uima.cas.TOP + + + stringArray + + uima.cas.StringArray + true + + + + + diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/data.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/data.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/data.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/data.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/debug-typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/debug-typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/debug-typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/debug-typesystem.xml diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/debug.xmi b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/debug.xmi similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/debug.xmi rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/debug.xmi diff --git a/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/typesystem.xml b/uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/typesystem.xml similarity index 100% rename from uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithFsList/typesystem.xml rename to uimaj-core/src/test/resources/CasSerializationDeserialization_XMI_1_1_PRETTY_Test/ser-ref/casWithLists/typesystem.xml From f5cc613a835fec52a6bb26b281de23074855f93a Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 11 Jul 2022 17:50:14 +0200 Subject: [PATCH 46/94] [UIMA-6480] Add tests with empty arrays to CAS de/ser-suite - Switch more tests from binary file compare to content compare because the binary file compare is defied by the empty arrays --- ...rializationDeserialization_COMPRESSED_FILTERED_TSI_Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test.java index 9beada61bd..73abd2b3e7 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/CasSerializationDeserialization_COMPRESSED_FILTERED_TSI_Test.java @@ -68,7 +68,7 @@ private static List oneWayDesSerScenarios() throws Exception } private static List roundTripDesSerScenarios() throws Exception { - return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingFileContents(desSerCycles, + return SerDesCasIOTestUtils.roundTripDesSerScenariosComparingCasContents(desSerCycles, CAS_FILE_NAME); } From c0e14fc2a826cff225c74c7a6974912c665945a2 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 11 Jul 2022 17:54:46 +0200 Subject: [PATCH 47/94] [UIMA-6454] Update dependencies (UIMA Java SDK 3.3.1) - maven-plugin-api 3.1.0 -> 3.2.4 - maven-core 3.0.3 -> 3.2.4 - maven-toolchains-plugin -> 3.1.0 (build) - change scope of Maven dependencies in Maven plugin modules to "provided" --- PearPackagingMavenPlugin/pom.xml | 5 +++-- jcasgen-maven-plugin/pom.xml | 9 ++++++--- uimaj-parent/pom.xml | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/PearPackagingMavenPlugin/pom.xml b/PearPackagingMavenPlugin/pom.xml index 0ba1e63cae..3c59cce932 100644 --- a/PearPackagingMavenPlugin/pom.xml +++ b/PearPackagingMavenPlugin/pom.xml @@ -43,7 +43,8 @@ org.apache.maven maven-plugin-api - 3.1.0 + ${maven.version} + provided @@ -56,7 +57,7 @@ org.apache.maven maven-core - 3.0.3 + ${maven.version} provided diff --git a/jcasgen-maven-plugin/pom.xml b/jcasgen-maven-plugin/pom.xml index 64587ea1d5..c0f1d4690f 100644 --- a/jcasgen-maven-plugin/pom.xml +++ b/jcasgen-maven-plugin/pom.xml @@ -16,7 +16,9 @@ specific language governing permissions and limitations under the License. --> - + 4.0.0 org.apache.uima @@ -41,12 +43,13 @@ org.apache.maven maven-plugin-api - 3.0.3 + ${maven.version} + provided org.apache.maven maven-core - 3.0.3 + ${maven.version} provided diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index eebd19a201..4723617c68 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -251,6 +251,7 @@ org.apache.maven.plugins maven-toolchains-plugin + 3.1.0 From 4100c3666b4ffcaea8dcc54851984a74f7881f3d Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 11 Jul 2022 18:09:39 +0200 Subject: [PATCH 48/94] [UIMA-6481] Enable issue management in GitHub repos - Enable issues and projects - Update description while we are at it and add the "java" keyword --- .asf.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index db9bdaf89c..6392b3bc76 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -16,7 +16,7 @@ # github: - description: "UIMA Java SDK, version 3 (in main), 2 (in main-v2)" + description: "Apache UIMA Java SDK" homepage: https://uima.apache.org dependabot_alerts: true dependabot_updates: false @@ -30,10 +30,11 @@ github: - apache - uima - text-analysis + - java features: wiki: false - issues: false - projects: false + issues: true + projects: true enabled_merge_buttons: squash: true merge: true From 6db34ef232e81746a013c39c356c14f709324a84 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 13 Jul 2022 08:57:29 +0200 Subject: [PATCH 49/94] [#222] Support comparing test files irrespective of line endings - Added `SerDesCasIOTestUtils.roundTripDesSerScenariosComparingFileContentsNormalizingNewlines` --- .../uima/cas/serdes/SerDesCasIOTestUtils.java | 25 +++++++++++++++++++ .../serdes/scenario/DesSerTestScenario.java | 6 +++++ 2 files changed, 31 insertions(+) diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/SerDesCasIOTestUtils.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/SerDesCasIOTestUtils.java index 2c4b9cc5ee..717f4500a5 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/SerDesCasIOTestUtils.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/SerDesCasIOTestUtils.java @@ -127,6 +127,31 @@ public static List roundTripDesSerScenariosComparingFileCont return confs; } + /** + * DESERIALIZE -> SERIALIZE scenarios using the reference data from the + * serialize/compare-to-reference data. + */ + public static List roundTripDesSerScenariosComparingFileContentsNormalizingNewlines( + Collection aDesSerCycles, String aCasFileName) + throws Exception { + Class caller = getCallerClass(); + + List confs = new ArrayList<>(); + + for (CasDesSerCycleConfiguration cycle : aDesSerCycles) { + try (Stream builders = DesSerTestScenario.builderCases(caller, + cycle, ROUND_TRIP, aCasFileName)) { + + builders.map(builder -> builder.withCycle(cycle::performCycle) + .withAssertion(DesSerTestScenario::assertFileContentsAreEqualNormalizingNewlines) + .build()) // + .forEach(confs::add); + } + } + + return confs; + } + /** * DESERIALIZE -> SERIALIZE scenarios using the reference data from the * serialize/compare-to-reference data. diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/scenario/DesSerTestScenario.java b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/scenario/DesSerTestScenario.java index 8c896cc3de..bf8c7f54e4 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/serdes/scenario/DesSerTestScenario.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/serdes/scenario/DesSerTestScenario.java @@ -121,6 +121,12 @@ public static void assertFileContentsAreEqual(Path aTargetCasFile, Path aReferen assertThat(contentOf(aTargetCasFile.toFile())).isEqualTo(contentOf(aReferenceCasFile.toFile())); } + public static void assertFileContentsAreEqualNormalizingNewlines(Path aTargetCasFile, + Path aReferenceCasFile) { + assertThat(contentOf(aTargetCasFile.toFile())) + .isEqualToNormalizingNewlines(contentOf(aReferenceCasFile.toFile())); + } + /** * Builder to build {@link DesSerTestScenario}. */ From 619f8f5fa1e15bff03fdc44408ab86f6f2c74a78 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 13 Jul 2022 09:34:12 +0200 Subject: [PATCH 50/94] [UIMA-6454] Update dependencies (UIMA Java SDK 3.3.1) - maven-plugin-plugin 3.6.1 -> 3.6.4 - japicmp-maven-plugin 0.15.3 -> 0.15.7 - inline eclipseP2RepoUrl property into repository declaration to avoid stressing out the resolver with variables --- uimaj-parent/pom.xml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index 4723617c68..1e2db4c589 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -98,7 +98,7 @@ ${eclipseP2RepoId} - ${eclipseP2RepoUrl} + https://download.eclipse.org/releases/2018-12/ p2 @@ -147,7 +147,6 @@ 1.8 org.eclipse.p2.201812 - https://download.eclipse.org/releases/2018-12/ 3.2.0 @@ -239,10 +238,10 @@ - + org.apache.maven.plugins maven-plugin-plugin - 3.6.1 + 3.6.4 @@ -251,6 +250,7 @@ org.apache.maven.plugins maven-toolchains-plugin + 3.1.0 @@ -269,6 +269,7 @@ + com.github.spotbugs spotbugs-maven-plugin 4.7.0.0 @@ -278,7 +279,8 @@ com.github.siom79.japicmp japicmp-maven-plugin - 0.15.3 + + 0.15.7 @@ -288,6 +290,7 @@ + org.codehaus.groovy groovy-jsr223 2.5.14 From 3f97c9feae7a65d54115b1e4f1021dfa06c2c9ea Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 13 Jul 2022 12:08:55 +0200 Subject: [PATCH 51/94] [UIMA-6454] Update dependencies (UIMA Java SDK 3.3.1) - groovy-jsr223 2.5.15 -> 2.5.17 (japicmp plugin dependency to support recent Java versions) --- uimaj-parent/pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index 1e2db4c589..eff05a5ad0 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -290,10 +290,11 @@ - + + org.codehaus.groovy groovy-jsr223 - 2.5.14 + 2.5.17 From 23a0d2fb468d0020b365fe9ca96ed9515e3ccfec Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 28 Jul 2022 12:01:47 +0200 Subject: [PATCH 52/94] Issue #226: Provide SPI interfaces to locate descriptors - Added TypeSystemDescriptionProvider interface --- .../spi/TypeSystemDescriptionProvider.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 uimaj-core/src/main/java/org/apache/uima/spi/TypeSystemDescriptionProvider.java diff --git a/uimaj-core/src/main/java/org/apache/uima/spi/TypeSystemDescriptionProvider.java b/uimaj-core/src/main/java/org/apache/uima/spi/TypeSystemDescriptionProvider.java new file mode 100644 index 0000000000..0672a66c69 --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/spi/TypeSystemDescriptionProvider.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ +package org.apache.uima.spi; + +import java.util.List; + +import org.apache.uima.resource.metadata.TypeSystemDescription; + +public interface TypeSystemDescriptionProvider { + List listTypeSystemDescriptions(); +} From 67c8a39413e8546043e16b95ceb861dc34c5f9f5 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 28 Jul 2022 12:40:36 +0200 Subject: [PATCH 53/94] Issue #225: Improve deployment in OSGi environments - Update to UIMA Parent POM 16-SNAPSHOT - Add OSGi metadata to several modules using the maven-bundle-plugin --- jVinci/marker-file-identifying-osgi-bundle | 0 jVinci/pom.xml | 64 ++++--- .../marker-file-identifying-osgi-bundle | 0 uimaj-adapter-vinci/pom.xml | 30 ++- .../marker-file-identifying-osgi-bundle | 0 uimaj-core/pom.xml | 78 ++++---- uimaj-cpe/marker-file-identifying-osgi-bundle | 0 uimaj-cpe/pom.xml | 26 +++ uimaj-parent/pom.xml | 10 +- .../marker-file-identifying-osgi-bundle | 0 uimaj-tools/pom.xml | 171 ++++++++++-------- 11 files changed, 239 insertions(+), 140 deletions(-) create mode 100644 jVinci/marker-file-identifying-osgi-bundle create mode 100644 uimaj-adapter-vinci/marker-file-identifying-osgi-bundle create mode 100644 uimaj-core/marker-file-identifying-osgi-bundle create mode 100644 uimaj-cpe/marker-file-identifying-osgi-bundle create mode 100644 uimaj-tools/marker-file-identifying-osgi-bundle diff --git a/jVinci/marker-file-identifying-osgi-bundle b/jVinci/marker-file-identifying-osgi-bundle new file mode 100644 index 0000000000..e69de29bb2 diff --git a/jVinci/pom.xml b/jVinci/pom.xml index dc773f297e..e96e8f05fb 100644 --- a/jVinci/pom.xml +++ b/jVinci/pom.xml @@ -17,29 +17,51 @@ specific language governing permissions and limitations under the License. --> - - 4.0.0 - - - org.apache.uima - uimaj-parent - 3.4.0-SNAPSHOT - ../uimaj-parent/pom.xml - - - jVinci - jar - Apache UIMA Base: ${project.artifactId}: Vinci Transport Library - This is a protocol used by the base UIMA Collection processing manager for supporting + + 4.0.0 + + + org.apache.uima + uimaj-parent + 3.4.0-SNAPSHOT + ../uimaj-parent/pom.xml + + + jVinci + bundle + + Apache UIMA Base: ${project.artifactId}: Vinci Transport Library + This is a protocol used by the base UIMA Collection processing manager for supporting networked deployment. See UIMA-AS as a more modern alternative supporting more standard protocols. - ${uimaWebsiteUrl} + ${uimaWebsiteUrl} + + + ${ibmNoticeText} + - - ${ibmNoticeText} - + + jVinci - - jVinci - + + + org.apache.felix + maven-bundle-plugin + + + JavaSE-1.8 + <_dsannotations>* + <_metatypeannotations>* + + org.apache.vinci.debug, + org.apache.vinci.transport, + org.apache.vinci.transport.* + + + + + + \ No newline at end of file diff --git a/uimaj-adapter-vinci/marker-file-identifying-osgi-bundle b/uimaj-adapter-vinci/marker-file-identifying-osgi-bundle new file mode 100644 index 0000000000..e69de29bb2 diff --git a/uimaj-adapter-vinci/pom.xml b/uimaj-adapter-vinci/pom.xml index e395edaa96..acb5883f0f 100644 --- a/uimaj-adapter-vinci/pom.xml +++ b/uimaj-adapter-vinci/pom.xml @@ -28,7 +28,8 @@ uimaj-adapter-vinci - jar + bundle + Apache UIMA Base: ${project.artifactId}: Vinci Adapter Provides the capability to connect to a remote analysis engine, using the Vinci protocol @@ -71,5 +72,32 @@ uima-adapter-vinci + + + + org.apache.felix + maven-bundle-plugin + + + JavaSE-1.8 + <_dsannotations>* + <_metatypeannotations>* + + !org.apache.uima.adapter.vinci, + !org.apache.uima.adapter.vinci.*, + !com.apple.eio, + org.slf4j.impl;resolution:=optional, + org.apache.logging.log4j.*;resolution:=optional, + org.apache.logging.slf4j.*;resolution:=optional, + * + + + org.apache.uima.adapter.vinci, + org.apache.uima.adapter.vinci.* + + + + + \ No newline at end of file diff --git a/uimaj-core/marker-file-identifying-osgi-bundle b/uimaj-core/marker-file-identifying-osgi-bundle new file mode 100644 index 0000000000..e69de29bb2 diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml index 6d2652205e..fdc9382bfc 100644 --- a/uimaj-core/pom.xml +++ b/uimaj-core/pom.xml @@ -28,7 +28,8 @@ uimaj-core - jar + bundle + Apache UIMA Base: ${project.artifactId} The core implementation of the UIMA Java Framework ${uimaWebsiteUrl} @@ -151,7 +152,6 @@ 5 work when run separately or by mvn, but fail when running all tests from Eclipse: Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element '....' --> - - - - - - - org.bitbucket.mstrobel - procyon-compilertools - 0.5.32 - - - - - org.bitbucket.mstrobel - procyon-core - 0.5.32 - - - - @@ -290,6 +253,31 @@ + + org.apache.felix + maven-bundle-plugin + + + JavaSE-1.8 + <_dsannotations>* + <_metatypeannotations>* + + !org.apache.uima, + !org.apache.uima.*, + !com.apple.eio, + org.slf4j.impl;resolution:=optional, + org.apache.logging.log4j.*;resolution:=optional, + org.apache.logging.slf4j.*;resolution:=optional, + * + + + org.apache.uima, + org.apache.uima.* + + + + + com.github.siom79.japicmp japicmp-maven-plugin - 0.15.3 + 0.15.7 + + + ${project.build.directory}/${project.build.finalName}.jar + + + com\.strobel\..* org\.apache\.logging\.log4j\..* diff --git a/uimaj-tools/marker-file-identifying-osgi-bundle b/uimaj-tools/marker-file-identifying-osgi-bundle new file mode 100644 index 0000000000..e69de29bb2 diff --git a/uimaj-tools/pom.xml b/uimaj-tools/pom.xml index 3d0de13c25..19e4a7bbef 100644 --- a/uimaj-tools/pom.xml +++ b/uimaj-tools/pom.xml @@ -17,80 +17,109 @@ specific language governing permissions and limitations under the License. --> - - 4.0.0 + + 4.0.0 - - org.apache.uima - uimaj-parent - 3.4.0-SNAPSHOT - ../uimaj-parent/pom.xml - + + org.apache.uima + uimaj-parent + 3.4.0-SNAPSHOT + ../uimaj-parent/pom.xml + - uimaj-tools - jar - Apache UIMA Base: ${project.artifactId}: Tools - Tooling supporting UIMA use - ${uimaWebsiteUrl} + uimaj-tools + bundle - - ${ibmNoticeText} - + Apache UIMA Base: ${project.artifactId}: Tools + Tooling supporting UIMA use + ${uimaWebsiteUrl} - - - org.apache.uima - uimaj-core - ${project.parent.version} - compile - - - org.apache.uima - uimaj-cpe - ${project.parent.version} - compile - - - org.apache.uima - uimaj-test-util - ${project.parent.version} - test - - - org.slf4j - slf4j-jdk14 - test - + + ${ibmNoticeText} + - - - uima-tools - - - src/main/resources - true - - - - - - org.apache.rat - apache-rat-plugin - - - default-cli - - - release.properties - src/main/resources/org/apache/uima/tools/migration/* - src/main/resources/org/apache/uima/tools/util/gui/about.txt - src/test/resources/pearTests/pearMergerTests/*.pear - - - - - - - - + + + org.apache.uima + uimaj-core + ${project.parent.version} + compile + + + org.apache.uima + uimaj-cpe + ${project.parent.version} + compile + + + org.apache.uima + uimaj-test-util + ${project.parent.version} + test + + + org.slf4j + slf4j-jdk14 + test + + + + + uima-tools + + + src/main/resources + true + + + + + + org.apache.rat + apache-rat-plugin + + + default-cli + + + release.properties + src/main/resources/org/apache/uima/tools/migration/* + src/main/resources/org/apache/uima/tools/util/gui/about.txt + src/test/resources/pearTests/pearMergerTests/*.pear + + + + + + + + + + org.apache.felix + maven-bundle-plugin + + + JavaSE-1.8 + <_dsannotations>* + <_metatypeannotations>* + + !org.apache.uima.tools, + !org.apache.uima.tools.*, + !com.apple.eio, + org.slf4j.impl;resolution:=optional, + org.apache.logging.log4j.*;resolution:=optional, + org.apache.logging.slf4j.*;resolution:=optional, + * + + + org.apache.uima.tools, + org.apache.uima.tools.* + + + + + + \ No newline at end of file From 240635155d11b1fd67342df1d99ce7b4b82ae360 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 28 Jul 2022 12:27:12 +0200 Subject: [PATCH 54/94] Issue #230: Remove version overrides in Maven plugin modules - Removed the version override --- PearPackagingMavenPlugin/pom.xml | 1 - jcasgen-maven-plugin/pom.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/PearPackagingMavenPlugin/pom.xml b/PearPackagingMavenPlugin/pom.xml index 7c244d50f1..7db9512070 100644 --- a/PearPackagingMavenPlugin/pom.xml +++ b/PearPackagingMavenPlugin/pom.xml @@ -46,7 +46,6 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.2 provided diff --git a/jcasgen-maven-plugin/pom.xml b/jcasgen-maven-plugin/pom.xml index a6e2fb6e1a..a96499f042 100644 --- a/jcasgen-maven-plugin/pom.xml +++ b/jcasgen-maven-plugin/pom.xml @@ -51,7 +51,6 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.2 provided From dd748b4161915c464e4d12ae88b56433b6aa59bc Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 28 Jul 2022 12:15:55 +0200 Subject: [PATCH 55/94] Issue #228 - Move the UimaDecompiler class - Move the decompiler class - Remove dependencies of uimaj-core that were only required by the decompiler - Add these dependencies to uimaj-v3migration-jcas --- uimaj-core/pom.xml | 14 --- uimaj-v3migration-jcas/pom.xml | 21 ++-- .../uima/migratev3/jcas/MigrateJCas.java | 110 +++++++++++------- .../uima/migratev3/jcas}/UimaDecompiler.java | 2 +- 4 files changed, 74 insertions(+), 73 deletions(-) rename {uimaj-core/src/main/java/org/apache/uima/cas/impl => uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas}/UimaDecompiler.java (99%) diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml index 6d2652205e..8bac476c40 100644 --- a/uimaj-core/pom.xml +++ b/uimaj-core/pom.xml @@ -184,20 +184,6 @@ --> - - - org.bitbucket.mstrobel - procyon-compilertools - 0.5.32 - - - - - org.bitbucket.mstrobel - procyon-core - 0.5.32 - - + org.bitbucket.mstrobel procyon-compilertools 0.5.32 - --> - - - org.ow2.asm - asm-tree - 5.0.4 + org.bitbucket.mstrobel + procyon-core + 0.5.32 - --> diff --git a/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java b/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java index 99d5ae45a9..c460b3f516 100644 --- a/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java +++ b/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java @@ -65,7 +65,6 @@ import org.apache.uima.UIMARuntimeException; import org.apache.uima.cas.impl.TypeImpl; import org.apache.uima.cas.impl.TypeSystemImpl; -import org.apache.uima.cas.impl.UimaDecompiler; import org.apache.uima.internal.util.CommandLineParser; import org.apache.uima.internal.util.Misc; import org.apache.uima.internal.util.UIMAClassLoader; @@ -354,9 +353,9 @@ private static class Container implements Comparable { this.parent = parent; if (parent != null) { parent.subContainers.add(this); - this.pearClasspath = parent.pearClasspath; // default, when expanding Jars. + pearClasspath = parent.pearClasspath; // default, when expanding Jars. } - this.rootOrig = root; + rootOrig = root; String s = root.toString().toLowerCase(); isJar = s.endsWith(".jar"); isPear = s.endsWith(".pear"); @@ -392,7 +391,7 @@ private Path installJarOrPear() { false); String newClasspath = ip.buildComponentClassPath(); String parentClasspath = parent.pearClasspath; - this.pearClasspath = (null == parentClasspath || 0 == parentClasspath.length()) + pearClasspath = (null == parentClasspath || 0 == parentClasspath.length()) ? newClasspath : newClasspath + File.pathSeparator + parentClasspath; } @@ -458,15 +457,19 @@ public int hashCode() { */ @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } Container other = (Container) obj; - if (id != other.id) - return false; + if (id != other.id) { + return false; + } return true; } @@ -681,7 +684,7 @@ private class CommonConverted { CommonConverted(String origSource, byte[] v2ByteCode, Path path, Container container, String fqcn_slash) { - this.v2Source = origSource; + v2Source = origSource; this.v2ByteCode = v2ByteCode; containersAndV2Paths.add(new ContainerAndPath(path, container)); this.fqcn_slash = fqcn_slash; @@ -707,7 +710,7 @@ int getId() { if (id < 0) { Integer nextId = nextCcId.computeIfAbsent(fqcn_slash, s -> INTEGER0); nextCcId.put(fqcn_slash, nextId + 1); - this.id = nextId; + id = nextId; } return id; } @@ -914,8 +917,9 @@ private void postProcessPearOrJar(Container container) { try { // copy the pear or jar so we don't change the original Path lastPartOfPath = container.rootOrig.getFileName(); - if (null == lastPartOfPath) - throw new RuntimeException("Internal Error"); + if (null == lastPartOfPath) { + throw new RuntimeException("Internal Error"); + } Path pearOrJarCopy = Paths.get(outputDirectory, container.isJar ? "jars" : "pears", Integer.toString(container.id), lastPartOfPath.toString()); @@ -1028,7 +1032,9 @@ private boolean compileV3SourcesCommon2(Container container) { boolean isEmpty = true; for (CommonConverted cc : container.convertedItems) { if (cc.v3SourcePath == null) - continue; // skip items that failed migration + { + continue; // skip items that failed migration + } isEmpty = false; // relativePathInContainer = the whole path with the first part (up to the end of the // container root) stripped off @@ -1723,14 +1729,17 @@ public void visit(MethodDeclaration n, Object ignore) { && Character.isUpperCase(name.charAt(3)) && !name.equals("getTypeIndexID")) { List ps = n.getParameters(); if (isGetter) { - if (ps.size() > 1) - break; + if (ps.size() > 1) { + break; + } } else { // is setter - if (ps.size() > 2 || ps.size() == 0) - break; + if (ps.size() > 2 || ps.size() == 0) { + break; + } if (ps.size() == 2) { - if (!getParmTypeName(ps, 0).equals("int")) - break; + if (!getParmTypeName(ps, 0).equals("int")) { + break; + } isArraySetter = true; } } @@ -1738,8 +1747,9 @@ public void visit(MethodDeclaration n, Object ignore) { // get the range-part-name and convert to v3 range ("Ref" changes to "Feature") String bodyString = n.getBody().get().toString(printWithoutComments); int i = bodyString.indexOf("jcasType.ll_cas.ll_"); - if (i < 0) - break; + if (i < 0) { + break; + } String s = bodyString.substring(i + "jcasType.ll_cas.ll_get".length()); // also for // ...ll_set - same // length! @@ -1907,8 +1917,9 @@ public void visit(MethodCallExpr n, Object ignore) { NodeList args; do { - if (get_set_method == null) - break; + if (get_set_method == null) { + break; + } /** remove checkArraybounds statement **/ if (n.getNameAsString().equals("checkArrayBounds") @@ -1925,8 +1936,9 @@ public void visit(MethodCallExpr n, Object ignore) { if (n.getNameAsString() .startsWith("ll_" + (useGetter ? "get" : "set") + rangeNameV2Part + "Value")) { args = n.getArguments(); - if (args.size() != (useGetter ? 2 : 3)) - break; + if (args.size() != (useGetter ? 2 : 3)) { + break; + } String suffix = useGetter ? "Nc" : rangeNamePart.equals("Feature") ? "NcWj" : "Nfc"; String methodName = "_" + (useGetter ? "get" : "set") + rangeNamePart + "Value" + suffix; args.remove(0); // remove the old addr arg @@ -1942,10 +1954,12 @@ public void visit(MethodCallExpr n, Object ignore) { String s = nname.substring(z.length()); s = s.substring(0, s.length() - "Value".length()); // s = "ShortArray", etc. - if (s.equals("RefArray")) - s = "FSArray"; - if (s.equals("IntArray")) - s = "IntegerArray"; + if (s.equals("RefArray")) { + s = "FSArray"; + } + if (s.equals("IntArray")) { + s = "IntegerArray"; + } EnclosedExpr ee = new EnclosedExpr( new CastExpr(new ClassOrInterfaceType(s), n.getArguments().get(0))); @@ -2200,8 +2214,9 @@ private Path makePath(String name) throws IOException { reportPathWorkaround(parent.toString(), p2.toString()); Path lastPartOfPath = p.getFileName(); - if (null == lastPartOfPath) - throw new RuntimeException(); + if (null == lastPartOfPath) { + throw new RuntimeException(); + } return Paths.get(p2.toString(), lastPartOfPath.toString()); } return p; @@ -2240,8 +2255,9 @@ private boolean reportPaths(String title, String fileName, return true; } System.out.println("\n" + title); - for (int i = 0; i < title.length(); i++) - System.out.print('='); + for (int i = 0; i < title.length(); i++) { + System.out.print('='); + } System.out.println(""); try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + fileName), @@ -2758,8 +2774,9 @@ private Node replaceInParent(Node n, Expression v) { } else if (parent instanceof ObjectCreationExpr) { List args = ((ObjectCreationExpr) parent).getArguments(); int i = args.indexOf(n); - if (i < 0) - throw new RuntimeException(); + if (i < 0) { + throw new RuntimeException(); + } args.set(i, v); } else { System.out.println(parent.getClass().getName()); @@ -2815,10 +2832,12 @@ private boolean hasTypeFields(NodeList> members) { for (VariableDeclarator vd : vds) { if (vd.getType().equals(intType)) { String n = vd.getNameAsString(); - if (n.equals("type")) - hasType = true; - if (n.equals("typeIndexID")) - hasTypeId = true; + if (n.equals("type")) { + hasType = true; + } + if (n.equals("typeIndexID")) { + hasTypeId = true; + } if (hasTypeId && hasType) { return true; } @@ -2854,8 +2873,9 @@ private void setHasJCasConstructors(NodeList> members) { for (BodyDeclaration bd : members) { if (bd instanceof ConstructorDeclaration) { List ps = ((ConstructorDeclaration) bd).getParameters(); - if (ps.size() == 0) - has0ArgConstructor = true; + if (ps.size() == 0) { + has0ArgConstructor = true; + } if (ps.size() == 1 && getParmTypeName(ps, 0).equals("JCas")) { has1ArgJCasConstructor = true; } diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java b/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/UimaDecompiler.java similarity index 99% rename from uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java rename to uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/UimaDecompiler.java index e422616cf9..2ea2aeb751 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/UimaDecompiler.java +++ b/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/UimaDecompiler.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.uima.cas.impl; +package org.apache.uima.migratev3.jcas; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; From cf514a9358ac0d5c1d4660b4316cd6174f32d86f Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 28 Jul 2022 16:47:22 +0200 Subject: [PATCH 56/94] Issue #226: Provide SPI interfaces to locate descriptors - Added SPI interfaces for index collections and type priorities providers --- .../uima/spi/FsIndexCollectionProvider.java | 27 +++++++++++++++++++ .../uima/spi/TypePrioritiesProvider.java | 27 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 uimaj-core/src/main/java/org/apache/uima/spi/FsIndexCollectionProvider.java create mode 100644 uimaj-core/src/main/java/org/apache/uima/spi/TypePrioritiesProvider.java diff --git a/uimaj-core/src/main/java/org/apache/uima/spi/FsIndexCollectionProvider.java b/uimaj-core/src/main/java/org/apache/uima/spi/FsIndexCollectionProvider.java new file mode 100644 index 0000000000..f197044a15 --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/spi/FsIndexCollectionProvider.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ +package org.apache.uima.spi; + +import java.util.List; + +import org.apache.uima.resource.metadata.FsIndexCollection; + +public interface FsIndexCollectionProvider { + List listFsIndexCollections(); +} diff --git a/uimaj-core/src/main/java/org/apache/uima/spi/TypePrioritiesProvider.java b/uimaj-core/src/main/java/org/apache/uima/spi/TypePrioritiesProvider.java new file mode 100644 index 0000000000..1299ade366 --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/spi/TypePrioritiesProvider.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ +package org.apache.uima.spi; + +import java.util.List; + +import org.apache.uima.resource.metadata.TypePriorities; + +public interface TypePrioritiesProvider { + List listTypePriorities(); +} From 61151eb94c380b193cf53523fa825b8179d070d1 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Thu, 28 Jul 2022 16:51:33 +0200 Subject: [PATCH 57/94] Issue #228 - Move the UimaDecompiler class - Ignore classes no longer in the classpath when calculating the API comparison --- uimaj-parent/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml index f1363343bc..26c750450a 100644 --- a/uimaj-parent/pom.xml +++ b/uimaj-parent/pom.xml @@ -274,6 +274,7 @@ + com\.strobel\..* org\.apache\.logging\.log4j\..* From 2f6316ecd14487724e79d37114ecd1b8e1e482c1 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 29 Jul 2022 13:46:41 +0200 Subject: [PATCH 58/94] Issue #235: Misleading error message when JCas type is not registered - Add new message - Use this message when an unregistered but defined type is being used --- .../main/java/org/apache/uima/cas/CASRuntimeException.java | 7 +++++++ .../main/java/org/apache/uima/cas/impl/TypeSystemImpl.java | 2 +- .../org/apache/uima/UIMAException_Messages.properties | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java b/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java index 643ce8c6b8..47e4282f9d 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java @@ -121,11 +121,18 @@ public class CASRuntimeException extends UIMARuntimeException { * supertypes "{3}". */ public static final String JCAS_MISMATCH_SUPERTYPE = "JCAS_MISMATCH_SUPERTYPE"; + /** * JCas type "{0}" used in Java code, but was not declared in the XML type descriptor. */ public static final String JCAS_TYPE_NOT_IN_CAS = "JCAS_TYPE_NOT_IN_CAS"; + /** + * JCas type "{0}" defined in CAS type system and used in Java code, but was not registered in + * JCasRegistry. + */ + public static final String JCAS_TYPE_NOT_IN_CAS_REGISTRY = "JCAS_TYPE_NOT_IN_CAS_REGISTRY"; + /** * CAS type system type "{0}" defines field "{1}" with range "{2}", but JCas class has range * "{3}". diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java index 1bea514f87..2c31e9b5df 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java @@ -2736,7 +2736,7 @@ private void throwMissingUIMAtype(int typeindex) { "Missing UIMA type, JCas Class name: %s, index: %d, jcasRegisteredTypes size: %d%n", className, typeindex, jcasRegisteredTypes.size()); dumpTypeSystem(); - throw new CASRuntimeException(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS, className); + throw new CASRuntimeException(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS_REGISTRY, className); } else { throw new CASRuntimeException(CASRuntimeException.JCAS_UNKNOWN_TYPE_NOT_IN_CAS); } diff --git a/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties b/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties index 1898db0edb..71df49ed0c 100644 --- a/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties +++ b/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties @@ -557,6 +557,7 @@ JCAS_CAS_NOT_V3 = JCas Class "{0}", loaded from "{1}", is missing required const JCAS_MISSING_FIELD_ACCESSOR = JCas Class "{0}" is missing required field accessor, or access not permitted, for field "{1}" during {2} operation. JCAS_CAS_MISMATCH = CAS type system doesn''t match JCas Type definition for type "{0}". JCAS_TYPE_NOT_IN_CAS = JCas type "{0}" used in Java code, but was not declared in the XML type descriptor. +JCAS_TYPE_NOT_IN_CAS_REGISTRY = JCas type "{0}" defined in CAS type system and used in Java code, but was not registered in JCasRegistry. JCAS_UNKNOWN_TYPE_NOT_IN_CAS = Unknown JCas type used in Java code but was not declared or imported in the XML descriptor for this component. JCAS_FIELD_MISSING_IN_TYPE_SYSTEM = JCAS class "{0}" defines a UIMA field "{1}" but the UIMA type doesn''t define that field. JCAS_FIELD_ADJ_OFFSET_CHANGED = In JCAS class "{0}", UIMA field "{1}" was set up when this class was previously loaded and initialized, to have an adjusted offset of "{2}" but now the feature has a different adjusted offset of "{3}"; this may be due to something else other than type system commit actions loading and initializing the JCas class, or to having a different non-compatible type system for this class, trying to use a common JCas cover class, which is not supported. From 120124c5be4ffa89c64e303dbf1df164e82c5ae8 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 29 Jul 2022 19:16:11 +0200 Subject: [PATCH 59/94] Issue #226: Provide SPI interfaces to locate descriptors - Added SPI for JCas classes - Added test that FSClassRegistry is able to load JCas classes through the SPI - Push exclusion of META-INF down into the bundle modules because we do not want to exclude the META-INF/services for SPI testing --- .gitignore | 1 - .../apache/uima/cas/impl/FSClassRegistry.java | 31 ++++++++++++++++ .../apache/uima/spi/JCasClassProvider.java | 27 ++++++++++++++ .../uima/cas/impl/FSClassRegistryTest.java | 16 +++++++++ .../uima/spi/JCasClassProviderForTesting.java | 35 +++++++++++++++++++ .../org.apache.uima.spi.JCasClassProvider | 1 + uimaj-ep-cas-editor-ide/.gitignore | 1 + uimaj-ep-cas-editor/.gitignore | 1 + uimaj-ep-configurator/.gitignore | 1 + uimaj-ep-debug/.gitignore | 1 + uimaj-ep-jcasgen/.gitignore | 1 + uimaj-ep-launcher/.gitignore | 1 + uimaj-ep-pear-packager/.gitignore | 1 + uimaj-ep-runtime/.gitignore | 1 + 14 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 uimaj-core/src/main/java/org/apache/uima/spi/JCasClassProvider.java create mode 100644 uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java create mode 100644 uimaj-core/src/test/resources/META-INF/services/org.apache.uima.spi.JCasClassProvider diff --git a/.gitignore b/.gitignore index 779de2a091..a7ddf4288d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ .project .settings target -META-INF checkpoint_synchPoint.xml checkpoint_synchPoint.xml.prev checkpoint.dat diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java index ee98243136..bb75e3b66f 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.ServiceLoader; import org.apache.uima.UIMAFramework; import org.apache.uima.UIMARuntimeException; @@ -52,6 +53,7 @@ import org.apache.uima.internal.util.UIMAClassLoader; import org.apache.uima.internal.util.WeakIdentityMap; import org.apache.uima.jcas.cas.TOP; +import org.apache.uima.spi.JCasClassProvider; import org.apache.uima.util.Level; import org.apache.uima.util.Logger; @@ -194,6 +196,8 @@ public abstract class FSClassRegistry { // abstract to prevent instantiating; th private static final WeakIdentityMap> cl_to_type2JCas = WeakIdentityMap .newHashMap(); // identity: key is classloader private static final WeakIdentityMap cl_to_type2JCasStacks; + private static final WeakIdentityMap>> cl_to_spiJCas = WeakIdentityMap + .newHashMap(); // private static final Map> cl_4pears_to_type2JCas = // Collections.synchronizedMap(new IdentityHashMap<>()); // identity: key is classloader @@ -921,6 +925,12 @@ private static Class maybeLoadJCas(TypeImpl ti, ClassLoader cl) { Class clazz = null; String className = ti.getJCasClassName(); + Map> spiJCasClasses = loadJCasClassesFromSPI(cl); + clazz = spiJCasClasses.get(className); + if (clazz != null) { + return clazz; + } + try { clazz = (Class) Class.forName(className, true, cl); } catch (ClassNotFoundException e) { @@ -933,6 +943,27 @@ private static Class maybeLoadJCas(TypeImpl ti, ClassLoader cl) { return clazz; } + static Map> loadJCasClassesFromSPI(ClassLoader cl) { + synchronized (cl_to_spiJCas) { + Map> spiJCas = cl_to_spiJCas.get(cl); + if (spiJCas != null) { + return spiJCas; + } + + Map> spiJCasClasses = new LinkedHashMap<>(); + ServiceLoader loader = ServiceLoader.load(JCasClassProvider.class, cl); + loader.forEach(provider -> { + List> list = provider.listJCasClasses(); + if (list != null) { + list.forEach(item -> spiJCasClasses.put(item.getName(), item)); + } + }); + cl_to_spiJCas.put(cl, spiJCasClasses); + + return spiJCasClasses; + } + } + // SYNCHRONIZED static synchronized MethodHandle getConstantIntMethodHandle(int i) { diff --git a/uimaj-core/src/main/java/org/apache/uima/spi/JCasClassProvider.java b/uimaj-core/src/main/java/org/apache/uima/spi/JCasClassProvider.java new file mode 100644 index 0000000000..a1f254523d --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/spi/JCasClassProvider.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ +package org.apache.uima.spi; + +import java.util.List; + +import org.apache.uima.jcas.cas.TOP; + +public interface JCasClassProvider { + List> listJCasClasses(); +} diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java b/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java index 78379f937e..99a37df5d1 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java @@ -19,9 +19,15 @@ package org.apache.uima.cas.impl; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +import java.util.Map; import org.apache.uima.UIMAFramework; +import org.apache.uima.cas.test.Sentence; +import org.apache.uima.cas.test.Token; import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.cas.TOP; import org.apache.uima.resource.ResourceManager; import org.apache.uima.util.CasCreationUtils; import org.apache.uima.util.Level; @@ -84,6 +90,16 @@ public void thatCreatingResourceManagersWithExtensionPathDoesNotFillUpCache() th } } + @Test + public void thatJCasClassesCanBeLoadedThroughSPI() throws Exception { + Map> jcasClasses = FSClassRegistry + .loadJCasClassesFromSPI(getClass().getClassLoader()); + + assertThat(jcasClasses).containsOnly( // + entry(Token.class.getName(), Token.class), // + entry(Sentence.class.getName(), Sentence.class)); + } + private void assertRegisteredClassLoaders(int aExpectedCount, String aDescription) { if (FSClassRegistry.clToType2JCasSize() > aExpectedCount) { FSClassRegistry.log_registered_classloaders(Level.INFO); diff --git a/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java b/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java new file mode 100644 index 0000000000..29f5a50959 --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ +package org.apache.uima.spi; + +import static java.util.Arrays.asList; + +import java.util.List; + +import org.apache.uima.cas.test.Sentence; +import org.apache.uima.cas.test.Token; +import org.apache.uima.jcas.cas.TOP; + +public class JCasClassProviderForTesting implements JCasClassProvider { + + @Override + public List> listJCasClasses() { + return asList(Token.class, Sentence.class); + } +} diff --git a/uimaj-core/src/test/resources/META-INF/services/org.apache.uima.spi.JCasClassProvider b/uimaj-core/src/test/resources/META-INF/services/org.apache.uima.spi.JCasClassProvider new file mode 100644 index 0000000000..59f27063fe --- /dev/null +++ b/uimaj-core/src/test/resources/META-INF/services/org.apache.uima.spi.JCasClassProvider @@ -0,0 +1 @@ +org.apache.uima.spi.JCasClassProviderForTesting diff --git a/uimaj-ep-cas-editor-ide/.gitignore b/uimaj-ep-cas-editor-ide/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-cas-editor-ide/.gitignore +++ b/uimaj-ep-cas-editor-ide/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-cas-editor/.gitignore b/uimaj-ep-cas-editor/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-cas-editor/.gitignore +++ b/uimaj-ep-cas-editor/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-configurator/.gitignore b/uimaj-ep-configurator/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-configurator/.gitignore +++ b/uimaj-ep-configurator/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-debug/.gitignore b/uimaj-ep-debug/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-debug/.gitignore +++ b/uimaj-ep-debug/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-jcasgen/.gitignore b/uimaj-ep-jcasgen/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-jcasgen/.gitignore +++ b/uimaj-ep-jcasgen/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-launcher/.gitignore b/uimaj-ep-launcher/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-launcher/.gitignore +++ b/uimaj-ep-launcher/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-pear-packager/.gitignore b/uimaj-ep-pear-packager/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-pear-packager/.gitignore +++ b/uimaj-ep-pear-packager/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ diff --git a/uimaj-ep-runtime/.gitignore b/uimaj-ep-runtime/.gitignore index 00d2ab71dd..f837dacf90 100644 --- a/uimaj-ep-runtime/.gitignore +++ b/uimaj-ep-runtime/.gitignore @@ -1,2 +1,3 @@ /.apt_generated/ /.apt_generated_tests/ +/META-INF/ From b5edf43491d0041eb99bafbad0b77e1dcb71390c Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 29 Jul 2022 23:11:16 +0200 Subject: [PATCH 60/94] Issue #238 - Form 6 serializes non-reachable FSes but should not - Instead of only setting the default v2IdRef flag (which has no effect), set the flag on the CAS currently being processed - Added unit test --- .../uima/cas/impl/BinaryCasSerDes6.java | 2 +- .../org/apache/uima/util/CasIOUtilsTest.java | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/BinaryCasSerDes6.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/BinaryCasSerDes6.java index 6d0cb9fbca..e6bcec21c2 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/BinaryCasSerDes6.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/BinaryCasSerDes6.java @@ -3044,7 +3044,7 @@ private void processIndexedFeatureStructures(final CASImpl cas1, boolean isWrite if (!isWrite) { // always have form 6 do just reachables, to mimic what v2 did AllFSs allFSs; - try (AutoCloseableNoException a = LowLevelCAS.ll_defaultV2IdRefs(false)) { + try (AutoCloseableNoException a = cas1.ll_enableV2IdRefs(false)) { allFSs = new AllFSs(cas1, mark, isTypeMapping ? fs -> isTypeInTgt(fs) : null, isTypeMapping ? typeMapper : null).getAllFSsAllViews_sofas_reachable(); // AllFSs internally already causes _save_to_cas_data() to be called, so we have to add all diff --git a/uimaj-core/src/test/java/org/apache/uima/util/CasIOUtilsTest.java b/uimaj-core/src/test/java/org/apache/uima/util/CasIOUtilsTest.java index 345ebf0f2d..d386b1c2c6 100644 --- a/uimaj-core/src/test/java/org/apache/uima/util/CasIOUtilsTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/util/CasIOUtilsTest.java @@ -19,6 +19,7 @@ package org.apache.uima.util; import static java.util.Arrays.asList; +import static org.apache.uima.cas.SerialFormat.COMPRESSED_FILTERED_TSI; import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayInputStream; @@ -32,14 +33,18 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import org.apache.uima.UIMAFramework; import org.apache.uima.cas.CAS; import org.apache.uima.cas.CASRuntimeException; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.SerialFormat; +import org.apache.uima.cas.impl.CASImpl; import org.apache.uima.jcas.cas.TOP; +import org.apache.uima.jcas.tcas.Annotation; import org.apache.uima.resource.metadata.FsIndexDescription; import org.apache.uima.resource.metadata.TypeDescription; import org.apache.uima.resource.metadata.TypeSystemDescription; @@ -337,6 +342,41 @@ public void testDocumentAnnotationIsNotResurrected() throws Exception { .extracting(fs -> fs.getType().getName()).containsExactly(customDocAnnoTypeName); } + @Test + public void thatBinaryForm6DoesOnlyIncludeReachableFSes() throws Exception { + CASImpl cas = (CASImpl) CasCreationUtils.createCas(); + byte[] buf; + try (AutoCloseableNoException a = cas.ll_enableV2IdRefs(true)) { + Annotation ann = cas.createAnnotation(cas.getAnnotationType(), 0, 1); + ann.addToIndexes(); + ann.removeFromIndexes(); + + Set allFSes = new LinkedHashSet<>(); + cas.walkReachablePlusFSsSorted(allFSes::add, null, null, null); + + assertThat(allFSes) // + .as("The annotation that was added and then removed before serialization should be found") // + .containsExactly(cas.getSofa(), ann); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + CasIOUtils.save(cas, bos, COMPRESSED_FILTERED_TSI); + buf = bos.toByteArray(); + } + + cas.reset(); + + try (AutoCloseableNoException a = cas.ll_enableV2IdRefs(true)) { + CasIOUtils.load(new ByteArrayInputStream(buf), cas); + + Set allFSes = new LinkedHashSet<>(); + cas.walkReachablePlusFSsSorted(allFSes::add, null, null, null); + + assertThat(allFSes) // + .as("The annotation that was added and then removed before serialization should not be found") // + .containsExactly(cas.getSofa()); + } + } + @AfterEach public void tearDown() throws Exception { cas.release(); From b7225a49cccb995f90d8f76fbfc1a9b51cacdfa4 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Sat, 30 Jul 2022 00:35:32 +0200 Subject: [PATCH 61/94] Issue #240: Helper annotation created by SelectFS should not survive - Prevent helper annotation from getting an ID and being held onto even when holding onto FSes is enabled - Added unit test --- .../org/apache/uima/cas/impl/CASImpl.java | 13 +++++++-- .../apache/uima/cas/impl/SelectFSs_impl.java | 5 +++- .../uima/cas/impl/SelectFsNoJCasTest.java | 27 ++++++++++++++++--- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java index b8c6236b5d..e3f57f52e8 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java @@ -5240,8 +5240,10 @@ public List walkReachablePlusFSsSorted(Consumer action_filtered, Marke List all = new AllFSs(this, mark, includeFilter, typeMapper) .getAllFSsAllViews_sofas_reachable().getAllFSsSorted(); List filtered = filterAboveMark(all, mark); - for (TOP fs : filtered) { - action_filtered.accept(fs); + if (action_filtered != null) { + for (TOP fs : filtered) { + action_filtered.accept(fs); + } } return all; } @@ -6169,6 +6171,13 @@ public AutoCloseableNoException ll_enableV2IdRefs(boolean enable) { return r; } + AutoCloseableNoException ll_forceEnableV2IdRefs(boolean enable) { + final boolean restoreState = svd.isId2Fs; + AutoCloseableNoException r = () -> svd.isId2Fs = restoreState; + svd.isId2Fs = enable; + return r; + } + // int allocIntData(int sz) { // // if (sz > INT_DATA_FOR_ALLOC_SIZE / 4) { diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java index 0322c2da17..c0d6abaa80 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/SelectFSs_impl.java @@ -63,6 +63,7 @@ import org.apache.uima.jcas.cas.TOP; import org.apache.uima.jcas.impl.JCasImpl; import org.apache.uima.jcas.tcas.Annotation; +import org.apache.uima.util.AutoCloseableNoException; // @formatter:off /** @@ -1020,7 +1021,9 @@ private Annotation makePosAnnot(int begin, int end) { if (end < begin) { throw new IllegalArgumentException("End value must be >= Begin value"); } - return new Annotation(jcas, begin, end); + try (AutoCloseableNoException c = ((CASImpl) jcas.getCas()).ll_forceEnableV2IdRefs(false)) { + return new Annotation(jcas, begin, end); + } } //@formatter:off diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/impl/SelectFsNoJCasTest.java b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SelectFsNoJCasTest.java index 79bc7d8ae3..cac79b523a 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/impl/SelectFsNoJCasTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SelectFsNoJCasTest.java @@ -19,7 +19,7 @@ package org.apache.uima.cas.impl; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import java.io.File; @@ -30,9 +30,11 @@ import org.apache.uima.resource.metadata.TypeSystemDescription; import org.apache.uima.resource.metadata.impl.TypePriorities_impl; import org.apache.uima.test.junit_extension.JUnitExtension; +import org.apache.uima.util.AutoCloseableNoException; import org.apache.uima.util.CasCreationUtils; import org.apache.uima.util.XMLInputSource; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; // tests without initializing JCas @@ -53,16 +55,33 @@ public static void setUpClass() throws Exception { null); } + @BeforeEach + public void setup() { + cas.reset(); + } + @Test public void testOpsNeedingAnnotation() { Type type = cas.getTypeSystem().getType("x.y.z.SentenceNoJCas"); FeatureStructure s = cas.createAnnotation(type, 0, 4); cas.indexRepository.addFS(s); - boolean b = cas. select(type).covering(1, 2).map(f -> f.getBegin()).findFirst() + assertThat(cas. select(type).covering(1, 2).map(f -> f.getBegin()).findFirst()) // .isPresent(); - - assertTrue(b); } + @Test + public void thatHelperAnnotationsDoNotRemainInCas() { + try (AutoCloseableNoException a = cas.ll_enableV2IdRefs(true)) { + cas.setDocumentText("text"); + assertThat(cas.walkReachablePlusFSsSorted(null, null, null, null)) + .containsExactly(cas.getSofa(), cas.getDocumentAnnotation()); + + cas.select(Annotation.class).at(0, 1); + + assertThat(cas.walkReachablePlusFSsSorted(null, null, null, null)) + .as("The helper annotation created by select must not be discovarably") + .containsExactly(cas.getSofa(), cas.getDocumentAnnotation()); + } + } } From 1384ee2dc84410cfb1de3cb75c2dc998fbaf8d87 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Sat, 30 Jul 2022 00:30:44 +0200 Subject: [PATCH 62/94] #238 - Form 6 serializes non-reachable FSes but should not - Removed test which actually tries to verify that non-indexed FSes get serialized and de-serialized - this is not the desired behavior --- .../java/org/apache/uima/cas/impl/SerDesForm6Test.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/impl/SerDesForm6Test.java b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SerDesForm6Test.java index 65f8344121..5b963b694d 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/impl/SerDesForm6Test.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/SerDesForm6Test.java @@ -66,7 +66,6 @@ import org.apache.uima.jcas.cas.TOP; import org.apache.uima.resource.ResourceInitializationException; import org.apache.uima.resource.metadata.TypeSystemDescription; -import org.apache.uima.util.AutoCloseableNoException; import org.apache.uima.util.CasCreationUtils; import org.apache.uima.util.impl.SerializationMeasures; import org.junit.jupiter.api.AfterEach; @@ -420,15 +419,6 @@ public void testAllKinds() { } } - @Test - public void testAllKindsV2() { - try (AutoCloseableNoException a = LowLevelCAS.ll_defaultV2IdRefs(); - AutoCloseableNoException b = casSrc.ll_enableV2IdRefs()) { // because casSrc set in - // setup - testAllKinds(); - } - } - // Test chains going through filtered type // Repeat below with OneType, and TwoTypes with filtered slot == fsRef From 7ede46368821196b15f58d3c7aa5f29eded4aa32 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 15 Aug 2022 10:56:35 +0200 Subject: [PATCH 63/94] Issue #226: Provide SPI interfaces to locate descriptors - When loading a class through an SPI, use its classloader for the generator lookup - Add own type classes for SPI testing to avoid interfering with existing tests --- uimaj-core/pom.xml | 2 + .../apache/uima/cas/impl/FSClassRegistry.java | 36 +- .../uima/cas/impl/FSClassRegistryTest.java | 8 +- .../org/apache/uima/jcas/test/generatedx.xml | 621 +++++++++--------- .../uima/spi/JCasClassProviderForTesting.java | 4 +- .../java/org/apache/uima/spi/SpiSentence.java | 99 +++ .../java/org/apache/uima/spi/SpiToken.java | 99 +++ 7 files changed, 538 insertions(+), 331 deletions(-) create mode 100644 uimaj-core/src/test/java/org/apache/uima/spi/SpiSentence.java create mode 100644 uimaj-core/src/test/java/org/apache/uima/spi/SpiToken.java diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml index 8bac476c40..c7dcebf63d 100644 --- a/uimaj-core/pom.xml +++ b/uimaj-core/pom.xml @@ -264,6 +264,8 @@ src/test/java/aa/*.java src/test/java/org/apache/uima/cas/test/*.java + src/test/java/org/apache/uima/spi/SpiToken.java + src/test/java/org/apache/uima/spi/SpiSentence.java src/test/java/org/apache/lang/LanguagePair.java src/test/java/sofa/test/CrossAnnotation.java src/test/java/x/y/z/*.java diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java index bb75e3b66f..b0142d3e66 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java @@ -645,7 +645,19 @@ static JCasClassInfo maybeCreateJCasClassInfo(TypeImpl ti, ClassLoader cl, } public static JCasClassInfo createJCasClassInfo(TypeImpl ti, ClassLoader cl, Lookup lookup) { - Class clazz = maybeLoadJCas(ti, cl); + Lookup actualLookup = lookup; + + // First we try the local classloader - this is necessary because it might be a PEAR situation + Class clazz = maybeLoadLocalJCas(ti, cl); + + // If the local classloader does not have the JCas wrapper, we try the SPI + if (clazz == null) { + Map> spiJCasClasses = loadJCasClassesFromSPI(cl); + clazz = spiJCasClasses.get(ti.getJCasClassName()); + if (clazz != null) { + actualLookup = getLookup(clazz.getClassLoader()); + } + } if (null == clazz || !TOP.class.isAssignableFrom(clazz)) { return null; @@ -667,7 +679,8 @@ public static JCasClassInfo createJCasClassInfo(TypeImpl ti, ClassLoader cl, Loo return null; } } - return createJCasClassInfo(clazz, ti, jcasType, lookup); + + return createJCasClassInfo(clazz, ti, jcasType, actualLookup); } // static AtomicLong time = IS_TIME_AUGMENT_FEATURES ? new AtomicLong(0) : null; @@ -914,33 +927,22 @@ private static String getAllSuperTypeNames(TypeImpl ti) { * * Synchronization: done outside this class * - * @param typeName - * - * @param cl * the class loader to use * @return the loaded / resolved class */ // @formatter:on - private static Class maybeLoadJCas(TypeImpl ti, ClassLoader cl) { - Class clazz = null; + @SuppressWarnings("unchecked") + private static Class maybeLoadLocalJCas(TypeImpl ti, ClassLoader cl) { String className = ti.getJCasClassName(); - - Map> spiJCasClasses = loadJCasClassesFromSPI(cl); - clazz = spiJCasClasses.get(className); - if (clazz != null) { - return clazz; - } - try { - clazz = (Class) Class.forName(className, true, cl); + return (Class) Class.forName(className, true, cl); } catch (ClassNotFoundException e) { // Class not found is normal, if there is no JCas for this class - return clazz; + return null; } catch (ExceptionInInitializerError e) { throw new RuntimeException("Exception while loading " + className, e); } - - return clazz; } static Map> loadJCasClassesFromSPI(ClassLoader cl) { diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java b/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java index 99a37df5d1..b6be4743d1 100644 --- a/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/FSClassRegistryTest.java @@ -24,11 +24,11 @@ import java.util.Map; import org.apache.uima.UIMAFramework; -import org.apache.uima.cas.test.Sentence; -import org.apache.uima.cas.test.Token; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.cas.TOP; import org.apache.uima.resource.ResourceManager; +import org.apache.uima.spi.SpiSentence; +import org.apache.uima.spi.SpiToken; import org.apache.uima.util.CasCreationUtils; import org.apache.uima.util.Level; import org.junit.Before; @@ -96,8 +96,8 @@ public void thatJCasClassesCanBeLoadedThroughSPI() throws Exception { .loadJCasClassesFromSPI(getClass().getClassLoader()); assertThat(jcasClasses).containsOnly( // - entry(Token.class.getName(), Token.class), // - entry(Sentence.class.getName(), Sentence.class)); + entry(SpiToken.class.getName(), SpiToken.class), // + entry(SpiSentence.class.getName(), SpiSentence.class)); } private void assertRegisteredClassLoaders(int aExpectedCount, String aDescription) { diff --git a/uimaj-core/src/test/java/org/apache/uima/jcas/test/generatedx.xml b/uimaj-core/src/test/java/org/apache/uima/jcas/test/generatedx.xml index 2c61e19c24..bf4352b8d1 100644 --- a/uimaj-core/src/test/java/org/apache/uima/jcas/test/generatedx.xml +++ b/uimaj-core/src/test/java/org/apache/uima/jcas/test/generatedx.xml @@ -1,350 +1,357 @@ - - - - - - -x.y.z.Sentence - -uima.tcas.Annotation - + + + x.y.z.Sentence + + uima.tcas.Annotation + sentenceLength - + uima.cas.Integer - -x.y.z.Token - -uima.tcas.Annotation - - -ttype - -x.y.z.TokenType - - -tokenFloatFeat - -uima.cas.Float - - -lemma - -uima.cas.String - - -lemmaList - -uima.cas.StringArray - - - - -x.y.z.TokenType - -uima.cas.TOP - - -x.y.z.Word - -x.y.z.TokenType - - -x.y.z.Separator - -x.y.z.TokenType - - -x.y.z.EndOfSentence - -x.y.z.TokenType - - -org.apache.lang.LanguagePair - -uima.cas.TOP - - -lang1 - -org.apache.lang.Group1 - - -lang2 - -org.apache.lang.Group2 - - -description - -uima.cas.String - - - - -org.apache.lang.Group1 - -uima.cas.String - - -"Chinese" - - - -"Japanese" - - - -"Korean" - - - -"English" - - - -"French" - - - -"German" - - - -"Italian" - - - -"Spanish" - - - -"Portuguese" - - - - - -org.apache.lang.Group2 - -uima.cas.String - - -"Arabic" - - - -"Czech" - - - -"Danish" - - - -"Dutch" - - - -"Finnish" - - - -"Greek" - - - -"Hebrew" - - - -"Hungarian" - - - -"Norwegian" - - - -"Polish" - - - -"Portuguese" - - - -"Russian" - - - -"Turkish" - - - - - -aa.Root - -uima.cas.TOP - - -arrayInt - -uima.cas.IntegerArray - - -arrayRef - -uima.cas.FSArray - - -arrayFloat - -uima.cas.FloatArray - - -arrayString - -uima.cas.StringArray - - -plainInt - -uima.cas.Integer - - -plainFloat - -uima.cas.Float - - -plainString - -uima.cas.String - - -plainRef -TokenType testMissingImport; -aa.Root - - + + x.y.z.Token + + uima.tcas.Annotation + + + ttype + + x.y.z.TokenType + + + tokenFloatFeat + + uima.cas.Float + + + lemma + + uima.cas.String + + + lemmaList + + uima.cas.StringArray + + + + + x.y.z.TokenType + + uima.cas.TOP + + + x.y.z.Word + + x.y.z.TokenType + + + x.y.z.Separator + + x.y.z.TokenType + + + x.y.z.EndOfSentence + + x.y.z.TokenType + + + org.apache.lang.LanguagePair + + uima.cas.TOP + + + lang1 + + org.apache.lang.Group1 + + + lang2 + + org.apache.lang.Group2 + + + description + + uima.cas.String + + + + + org.apache.lang.Group1 + + uima.cas.String + + + "Chinese" + + + + "Japanese" + + + + "Korean" + + + + "English" + + + + "French" + + + + "German" + + + + "Italian" + + + + "Spanish" + + + + "Portuguese" + + + + + + org.apache.lang.Group2 + + uima.cas.String + + + "Arabic" + + + + "Czech" + + + + "Danish" + + + + "Dutch" + + + + "Finnish" + + + + "Greek" + + + + "Hebrew" + + + + "Hungarian" + + + + "Norwegian" + + + + "Polish" + + + + "Portuguese" + + + + "Russian" + + + + "Turkish" + + + + + + aa.Root + + uima.cas.TOP + + + arrayInt + + uima.cas.IntegerArray + + + arrayRef + + uima.cas.FSArray + + + arrayFloat + + uima.cas.FloatArray + + + arrayString + + uima.cas.StringArray + + + plainInt + + uima.cas.Integer + + + plainFloat + + uima.cas.Float + + + plainString + + uima.cas.String + + + plainRef + TokenType testMissingImport; + aa.Root + + plainLong - + uima.cas.Long plainDouble - + uima.cas.Double arrayLong - + uima.cas.LongArray arrayDouble - + uima.cas.DoubleArray - - -aa.MissingInCas - -uima.cas.TOP - - -aa.MissingFeatureInCas - -uima.cas.TOP - - -haveThisOne - -uima.cas.Integer - - -missingThisOne - -uima.cas.Float - - -changedFType - -uima.cas.String - - - - -aa.AbstractType - -uima.cas.TOP - - -abstractInt - -uima.cas.Integer - - - - -aa.ConcreteType - -aa.AbstractType - - -concreteString - -uima.cas.String - - - - + + + aa.MissingInCas + + uima.cas.TOP + + + aa.MissingFeatureInCas + + uima.cas.TOP + + + haveThisOne + + uima.cas.Integer + + + missingThisOne + + uima.cas.Float + + + changedFType + + uima.cas.String + + + + + aa.AbstractType + + uima.cas.TOP + + + abstractInt + + uima.cas.Integer + + + + + aa.ConcreteType + + aa.AbstractType + + + concreteString + + uima.cas.String + + + + org.apache.uima.cas.test.CrossAnnotation - + uima.tcas.Annotation otherAnnotation - + uima.tcas.Annotation - + org.apache.uima.cas.test.Sentence - + uima.tcas.Annotation org.apache.uima.cas.test.Token - + + uima.tcas.Annotation + + + org.apache.uima.spi.SpiToken + + uima.tcas.Annotation + + + org.apache.uima.spi.SpiSentence + uima.tcas.Annotation diff --git a/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java b/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java index 29f5a50959..7f762a9fd5 100644 --- a/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java +++ b/uimaj-core/src/test/java/org/apache/uima/spi/JCasClassProviderForTesting.java @@ -22,14 +22,12 @@ import java.util.List; -import org.apache.uima.cas.test.Sentence; -import org.apache.uima.cas.test.Token; import org.apache.uima.jcas.cas.TOP; public class JCasClassProviderForTesting implements JCasClassProvider { @Override public List> listJCasClasses() { - return asList(Token.class, Sentence.class); + return asList(SpiToken.class, SpiSentence.class); } } diff --git a/uimaj-core/src/test/java/org/apache/uima/spi/SpiSentence.java b/uimaj-core/src/test/java/org/apache/uima/spi/SpiSentence.java new file mode 100644 index 0000000000..0491a2e21b --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/spi/SpiSentence.java @@ -0,0 +1,99 @@ +// @formatter:off +/* Apache UIMA v3 - First created by JCasGen Mon Aug 15 10:39:23 CEST 2022 */ + +package org.apache.uima.spi; + + + +import org.apache.uima.cas.impl.CASImpl; +import org.apache.uima.cas.impl.TypeImpl; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.JCasRegistry; +import org.apache.uima.jcas.tcas.Annotation; + + +/** + * Updated by JCasGen Mon Aug 15 10:39:23 CEST 2022 + * XML source: /Users/bluefire/git/uima-uimaj/uimaj-core/src/test/java/org/apache/uima/jcas/test/generatedx.xml + * @generated */ +public class SpiSentence extends Annotation { + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static String _TypeName = "org.apache.uima.spi.SpiSentence"; + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int typeIndexID = JCasRegistry.register(SpiSentence.class); + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int type = typeIndexID; + /** @generated + * @return index of the type + */ + @Override + public int getTypeIndexID() {return typeIndexID;} + + + /* ******************* + * Feature Offsets * + * *******************/ + + + + /* Feature Adjusted Offsets */ + + + /** Never called. Disable default constructor + * @generated */ + @Deprecated + @SuppressWarnings ("deprecation") + protected SpiSentence() {/* intentionally empty block */} + + /** Internal - constructor used by generator + * @generated + * @param casImpl the CAS this Feature Structure belongs to + * @param type the type of this Feature Structure + */ + public SpiSentence(TypeImpl type, CASImpl casImpl) { + super(type, casImpl); + readObject(); + } + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + */ + public SpiSentence(JCas jcas) { + super(jcas); + readObject(); + } + + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + * @param begin offset to the begin spot in the SofA + * @param end offset to the end spot in the SofA + */ + public SpiSentence(JCas jcas, int begin, int end) { + super(jcas); + setBegin(begin); + setEnd(end); + readObject(); + } + + /** + * + * Write your own initialization here + * + * + * @generated modifiable + */ + private void readObject() {/*default - does nothing empty block */} + +} diff --git a/uimaj-core/src/test/java/org/apache/uima/spi/SpiToken.java b/uimaj-core/src/test/java/org/apache/uima/spi/SpiToken.java new file mode 100644 index 0000000000..fa0adf40d3 --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/spi/SpiToken.java @@ -0,0 +1,99 @@ +// @formatter:off +/* Apache UIMA v3 - First created by JCasGen Mon Aug 15 10:39:23 CEST 2022 */ + +package org.apache.uima.spi; + + + +import org.apache.uima.cas.impl.CASImpl; +import org.apache.uima.cas.impl.TypeImpl; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.JCasRegistry; +import org.apache.uima.jcas.tcas.Annotation; + + +/** + * Updated by JCasGen Mon Aug 15 10:39:23 CEST 2022 + * XML source: /Users/bluefire/git/uima-uimaj/uimaj-core/src/test/java/org/apache/uima/jcas/test/generatedx.xml + * @generated */ +public class SpiToken extends Annotation { + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static String _TypeName = "org.apache.uima.spi.SpiToken"; + + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int typeIndexID = JCasRegistry.register(SpiToken.class); + /** @generated + * @ordered + */ + @SuppressWarnings ("hiding") + public final static int type = typeIndexID; + /** @generated + * @return index of the type + */ + @Override + public int getTypeIndexID() {return typeIndexID;} + + + /* ******************* + * Feature Offsets * + * *******************/ + + + + /* Feature Adjusted Offsets */ + + + /** Never called. Disable default constructor + * @generated */ + @Deprecated + @SuppressWarnings ("deprecation") + protected SpiToken() {/* intentionally empty block */} + + /** Internal - constructor used by generator + * @generated + * @param casImpl the CAS this Feature Structure belongs to + * @param type the type of this Feature Structure + */ + public SpiToken(TypeImpl type, CASImpl casImpl) { + super(type, casImpl); + readObject(); + } + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + */ + public SpiToken(JCas jcas) { + super(jcas); + readObject(); + } + + + /** @generated + * @param jcas JCas to which this Feature Structure belongs + * @param begin offset to the begin spot in the SofA + * @param end offset to the end spot in the SofA + */ + public SpiToken(JCas jcas, int begin, int end) { + super(jcas); + setBegin(begin); + setEnd(end); + readObject(); + } + + /** + * + * Write your own initialization here + * + * + * @generated modifiable + */ + private void readObject() {/*default - does nothing empty block */} + +} From 7b800e5143fc03073cab003ec398ea66ca1fac87 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 15 Aug 2022 10:57:02 +0200 Subject: [PATCH 64/94] [UIMA-6481] Enable issue management in GitHub repos - Update template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a61bf3d399..b2e525db29 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -13,5 +13,5 @@ * [ ] PR adds/updates documentation **Organizational** -- [ ] PR includes new dependencies. +- [ ] PR adds/updates dependencies. Only dependencies under [approved licenses](http://www.apache.org/legal/resolved.html#category-a) are allowed. LICENSE and NOTICE files in the respective modules where dependencies have been added as well as in the project root have been updated. From 84b867261e34cca8a8d756bbb063b93448fd179e Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 15 Aug 2022 11:32:13 +0200 Subject: [PATCH 65/94] Issue #235: Misleading error message when JCas type is not registered - Fix test --- .../org/apache/uima/jcas/test/JCasTest.java | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java index 78fe7decc0..359c51c585 100644 --- a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java @@ -19,10 +19,13 @@ package org.apache.uima.jcas.test; +import static org.apache.uima.util.CasCreationUtils.createCas; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.InstanceOfAssertFactories.throwable; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Iterator; @@ -70,7 +73,6 @@ import org.apache.uima.jcas.tcas.Annotation; import org.apache.uima.resource.metadata.impl.TypeSystemDescription_impl; import org.apache.uima.test.junit_extension.JUnitExtension; -import org.apache.uima.util.CasCreationUtils; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -126,8 +128,9 @@ public void checkOkMissingImport(Exception e1) { // initializing JCas type: aa.Root, feature: testMissingImport\n")) { // assertTrue(false); // } - } else + } else { assertTrue(false); + } } public void checkExpectedBadCASError(Exception e1, String err) { @@ -139,8 +142,9 @@ public void checkExpectedBadCASError(Exception e1, String err) { if (!(e.getMessageKey().equals(err))) { assertTrue(false); } - } else + } else { assertTrue(false); + } } @AfterEach @@ -998,22 +1002,22 @@ public void testOtherListAPI() { @Test public void testUndefinedType() throws Exception { // create jcas with no type system - JCas localJcas = CasCreationUtils.createCas(new TypeSystemDescription_impl(), null, null) - .getJCas(); + JCas localJcas = createCas(new TypeSystemDescription_impl(), null, null).getJCas(); localJcas.setDocumentText("This is a test."); - try { - // this should throw an exception - localJcas.getCasType(Sentence.type); - fail(); - } catch (CASRuntimeException e) { - assertEquals(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS, e.getMessageKey()); - } + + assertThatExceptionOfType(CASRuntimeException.class) // + .isThrownBy(() -> localJcas.getCasType(Sentence.type)) // + .asInstanceOf(throwable(CASRuntimeException.class)) // + .extracting(CASRuntimeException::getMessageKey) // + .isEqualTo(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS_REGISTRY); + // check that this does not leave JCAS in an inconsistent state // (a check for bug UIMA-738) Iterator iter = localJcas.getAnnotationIndex().iterator(); - assertTrue(iter.hasNext()); - Annotation annot = iter.next(); - assertEquals("This is a test.", annot.getCoveredText()); + assertThat(iter).hasNext(); + assertThat(iter.next()) // + .extracting(Annotation::getCoveredText) // + .isEqualTo("This is a test."); } /* From 46b15032e10b3ee7f6105881aa222061e863811c Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 15 Aug 2022 11:32:39 +0200 Subject: [PATCH 66/94] [No issue] Auto-formatting --- .../java/org/apache/uima/pear/util/FileUtil.java | 10 ++++------ .../pear/util/PearInstallationVerificationTest.java | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java b/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java index ae18a1a10e..50a8ff9704 100644 --- a/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java +++ b/uimaj-core/src/main/java/org/apache/uima/pear/util/FileUtil.java @@ -145,9 +145,8 @@ public boolean accept(File file) { boolean extAccepted = true; if (_dirPath != null) { String parentDir = file.getParent(); - dirAccepted = parentDir != null - && parentDir.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR) - .startsWith(_dirPath); + dirAccepted = parentDir != null && parentDir + .replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR).startsWith(_dirPath); } if (_fileExt != null) { extAccepted = file.getPath().toLowerCase().endsWith(_fileExt); @@ -789,9 +788,8 @@ public static long extractFilesFromJar(JarFile jarFile, File targetDir, FileFilt File file = new File(targetDir, jarEntry.getName()); if (!normalizeToUnix(file.getCanonicalPath()).startsWith(prefix)) { - throw new IOException( - "Can only write within target folder [" + targetDir.getAbsolutePath() - + "]. Please validate ZIP contents."); + throw new IOException("Can only write within target folder [" + targetDir.getAbsolutePath() + + "]. Please validate ZIP contents."); } File dir = file.getParentFile(); diff --git a/uimaj-core/src/test/java/org/apache/uima/pear/util/PearInstallationVerificationTest.java b/uimaj-core/src/test/java/org/apache/uima/pear/util/PearInstallationVerificationTest.java index 1b331e30ad..3be91930ac 100644 --- a/uimaj-core/src/test/java/org/apache/uima/pear/util/PearInstallationVerificationTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/pear/util/PearInstallationVerificationTest.java @@ -42,28 +42,25 @@ */ public class PearInstallationVerificationTest { @Test - public void testAePearVerification(@TempDir - File temp) throws Exception { + public void testAePearVerification(@TempDir File temp) throws Exception { assertThatPearInstalls(getFile("pearTests/analysisEngine.pear"), temp); } @Test - public void testCcPearVerification(@TempDir - File temp) throws Exception { + public void testCcPearVerification(@TempDir File temp) throws Exception { assertThatPearInstalls(getFile("pearTests/casConsumer.pear"), temp); } @Test - public void testTsPearVerification(@TempDir - File temp) throws Exception { + public void testTsPearVerification(@TempDir File temp) throws Exception { assertThatPearInstalls(getFile("pearTests/typeSystem.pear"), temp); } // TODO: create testcases for ci, cr, cpe pear packages @Test - public void thatSpecialXmlCharactersInTargetPathDoNotBreakInstallation(@TempDir - File temp) throws Exception { + public void thatSpecialXmlCharactersInTargetPathDoNotBreakInstallation(@TempDir File temp) + throws Exception { File folder = new File(temp, "!'&"); folder.mkdirs(); assertThatPearInstalls(getFile("pearTests/analysisEngine.pear"), From e0b4cd575bc300af43db60abaa606d93d2e5ff01 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 15 Aug 2022 11:36:01 +0200 Subject: [PATCH 67/94] Issue #226: Provide SPI interfaces to locate descriptors - Exclude SPI control file from rat check --- uimaj-core/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml index c7dcebf63d..21e0e70d9f 100644 --- a/uimaj-core/pom.xml +++ b/uimaj-core/pom.xml @@ -260,7 +260,8 @@ src/test/resources/pearTests/*.pear src/test/resources/pearTests/encodingTests/* src/test/resources/SequencerTest/*.txt - src/test/resources/SerDes*/SavedInts.binary + src/test/resources/SerDes*/SavedInts.binary + src/test/resources/META-INF/services/org.apache.uima.spi.JCasClassProvider src/test/java/aa/*.java src/test/java/org/apache/uima/cas/test/*.java From 07d5d89d2547ba384afcc35e976f4ee14cb5571b Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 15 Aug 2022 13:36:53 +0200 Subject: [PATCH 68/94] Issue #226: Provide SPI interfaces to locate descriptors - Added a bit of documentation --- .../src/docs/asciidoc/uv3.spi.adoc | 52 +++++++++++++++++++ .../docs/asciidoc/version_3_users_guide.adoc | 2 + 2 files changed, 54 insertions(+) create mode 100644 uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc diff --git a/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc b/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc new file mode 100644 index 0000000000..18b90f1582 --- /dev/null +++ b/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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. + +[[_uv3.custom_java_objects]] += Type discovery via SPI + +JCas types and associated type system descriptions can be made discoverable by UIMA using Java's +SPI mechanism. + +NOTE: The core UIMA Java SDK currently only this mechanism to discover JCas classes. SPI-based + auto-discovery of type system descriptions is supported by uimaFIT 3.4.0 and higher. + +SPI-based JCas class discovery is important in situation where multiple classloaders are used, e.g. +in OSGi environments. This is because JCas classes must be globally unique in the entire system +(with the exception of PEARs which can have their own JCas classes). So if JCas classes are to be +provided through different class loaders (e.g. OSGI bundle classloaders), they must be announced via +SPI, otherwise UIMA will not be able to reliably associated the JCas classes with their unique +classloader. + +To announce JCas classes via SPI, create a file `META-INF/services/org.apache.uima.spi.JCasClassProvider` +and in the file, place implementations of the interface `org.apache.uima.spi.JCasClassProvider`, one +per line. + +Here is a trivial example implementation of the interface that announces two JCas classes. + +[source] +---- +public class MyJCasClassProvider implements JCasClassProvider { + + @Override + public List> listJCasClasses() { + return asList(MyToken.class, MySentence.class); + } +} +---- + +More elaborate implementations might e.g. use uimaFIT to auto-detect types and if there is a JCas +class for any of these types, announce them. diff --git a/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc b/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc index b6f0cd89df..253ad045fc 100644 --- a/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc +++ b/uima-doc-v3-users-guide/src/docs/asciidoc/version_3_users_guide.adoc @@ -34,6 +34,8 @@ include::uv3.select.adoc[leveloffset=+1] include::uv3.annotation_predicates.adoc[leveloffset=+1] +include::uv3.spi.adoc[leveloffset=+1] + include::uv3.custom_java_objects.adoc[leveloffset=+1] include::uv3.logging.adoc[leveloffset=+1] From eb8eb8bc0256bed2fadc167df621d5a906b49dc7 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Wed, 17 Aug 2022 18:17:20 +0200 Subject: [PATCH 69/94] Issue #225: Improve deployment in OSGi environments - Make JCas SPI discovery available in OSGi --- uimaj-core/pom.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml index ec6a13b011..8286b55942 100644 --- a/uimaj-core/pom.xml +++ b/uimaj-core/pom.xml @@ -17,7 +17,9 @@ specific language governing permissions and limitations under the License. --> - + 4.0.0 @@ -29,7 +31,7 @@ uimaj-core bundle - + Apache UIMA Base: ${project.artifactId} The core implementation of the UIMA Java Framework ${uimaWebsiteUrl} @@ -276,6 +278,10 @@ org.apache.uima, org.apache.uima.* + + osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)", + osgi.serviceloader;filter:="(osgi.serviceloader=org.apache.uima.spi.JCasClassProvider)";cardinality:=multiple + From 1c1b3bc66a27795b3bd438db49e590f3e5699b1b Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 26 Aug 2022 12:43:52 +0200 Subject: [PATCH 70/94] Issue #225: Improve deployment in OSGi environments - SPI resolution should be optional --- uimaj-core/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml index 8286b55942..29e43753ba 100644 --- a/uimaj-core/pom.xml +++ b/uimaj-core/pom.xml @@ -279,8 +279,8 @@ org.apache.uima.* - osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)", - osgi.serviceloader;filter:="(osgi.serviceloader=org.apache.uima.spi.JCasClassProvider)";cardinality:=multiple + osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional, + osgi.serviceloader;filter:="(osgi.serviceloader=org.apache.uima.spi.JCasClassProvider)";cardinality:=multiple;resolution:=optional From f3b0e300c159952c79756223a3d17dc9bde3aa4e Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 26 Aug 2022 15:28:45 +0200 Subject: [PATCH 71/94] #245 - Utility method for loading type systems in SPI providers - Added utility method --- .../org/apache/uima/util/TypeSystemUtil.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java index 302daaed21..0879e04529 100644 --- a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java +++ b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java @@ -19,6 +19,8 @@ package org.apache.uima.util; +import java.io.IOException; +import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -30,13 +32,72 @@ import org.apache.uima.cas.Type; import org.apache.uima.cas.TypeSystem; import org.apache.uima.cas.impl.LowLevelTypeSystem; +import org.apache.uima.resource.ResourceManager; +import org.apache.uima.resource.impl.ResourceManager_impl; import org.apache.uima.resource.metadata.AllowedValue; import org.apache.uima.resource.metadata.FeatureDescription; import org.apache.uima.resource.metadata.TypeDescription; import org.apache.uima.resource.metadata.TypeSystemDescription; +import org.apache.uima.spi.TypeSystemDescriptionProvider; public class TypeSystemUtil { + /** + * Loads type system descriptions and resolves their imports. For example when you place a + * {@link TypeSystemDescriptionProvider} implementation and place the type system descriptions it + * should provide in the same package, you can use this method to conveniently load them simply by + * name in the provider implementation. + * + *

+   * public class MyTypeSystemDescriptionProvider implements TypeSystemDescriptionProvider {
+   *   {@code @Override}
+   *   public List listTypeSystemDescriptions() {
+   *     return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(this, "TypeSystem1.xml",
+   *             "TypeSystem2.xml");
+   *   }
+   * }
+   * 
+ * + * + * @param aContext + * a context class. If the locations are not absolute, then they are looked up relative + * to this context class as per {@link Class#getResource(String)}. + * @param typeSystemDescriptionLocations + * type system description locations to load. + * @return list of the loaded and resolved descriptions. + */ + public static List loadTypeSystemDescriptionsFromClasspath( + Class aContext, String... typeSystemDescriptionLocations) { + + ResourceManager resMgr = new ResourceManager_impl(aContext.getClassLoader()); + try { + List typeSystemDescriptions = new ArrayList<>(); + + for (String typeSystem : typeSystemDescriptionLocations) { + URL resource = aContext.getResource(typeSystem); + if (resource == null) { + UIMAFramework.getLogger() + .error("Unable to locate type system description as a resource [{}]", typeSystem); + continue; + } + + try { + TypeSystemDescription tsd = UIMAFramework.getXMLParser() + .parseTypeSystemDescription(new XMLInputSource(resource)); + tsd.resolveImports(resMgr); + typeSystemDescriptions.add(tsd); + } catch (InvalidXMLException | IOException e) { + UIMAFramework.getLogger().error("Error loading type system description [{}] from [{}]", + typeSystem, resource, e); + } + } + + return typeSystemDescriptions; + } finally { + resMgr.destroy(); + } + } + /** * Convert a {@link TypeSystem} to an equivalent {@link TypeSystemDescription}. * From 42f25d3e76b0e09f1794d4ca06a472f5e315db8f Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 26 Aug 2022 15:34:22 +0200 Subject: [PATCH 72/94] #245 - Utility method for loading type systems in SPI providers - Update documentation --- .../src/docs/asciidoc/uv3.spi.adoc | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc b/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc index 18b90f1582..3e785a2001 100644 --- a/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc +++ b/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc @@ -15,9 +15,11 @@ // specific language governing permissions and limitations // under the License. -[[_uv3.custom_java_objects]] +[[_uv3.spi]] = Type discovery via SPI +== JCas class discovery + JCas types and associated type system descriptions can be made discoverable by UIMA using Java's SPI mechanism. @@ -50,3 +52,26 @@ public class MyJCasClassProvider implements JCasClassProvider { More elaborate implementations might e.g. use uimaFIT to auto-detect types and if there is a JCas class for any of these types, announce them. + +== Type system description discovery + +The core UIMA framework defines the `TypeSystemDescriptionProvider` interface to also enable +type system discovery via SPI. However, note that currently only uimaFIT actually implements +the type system discovery. + +Here is an example of how to implement a type system description provider for use with +uimaFIT: + + +[source] +---- +import org.apache.uima.util.TypeSystemUtil; + +public class MyTypeSystemDescriptionProvider implements TypeSystemDescriptionProvider { + @Override} + public List listTypeSystemDescriptions() { + return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(this, "TypeSystem1.xml", + "TypeSystem2.xml"); + } +} +---- From 44074f41638ff1727f5be12bc9ba8cc302df08ee Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 26 Aug 2022 15:36:38 +0200 Subject: [PATCH 73/94] #245 - Utility method for loading type systems in SPI providers - Fix documentation --- uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc | 2 +- .../src/main/java/org/apache/uima/util/TypeSystemUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc b/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc index 3e785a2001..fac8ed9362 100644 --- a/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc +++ b/uima-doc-v3-users-guide/src/docs/asciidoc/uv3.spi.adoc @@ -70,7 +70,7 @@ import org.apache.uima.util.TypeSystemUtil; public class MyTypeSystemDescriptionProvider implements TypeSystemDescriptionProvider { @Override} public List listTypeSystemDescriptions() { - return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(this, "TypeSystem1.xml", + return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(getClass(), "TypeSystem1.xml", "TypeSystem2.xml"); } } diff --git a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java index 0879e04529..75726fb537 100644 --- a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java +++ b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java @@ -52,7 +52,7 @@ public class TypeSystemUtil { * public class MyTypeSystemDescriptionProvider implements TypeSystemDescriptionProvider { * {@code @Override} * public List listTypeSystemDescriptions() { - * return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(this, "TypeSystem1.xml", + * return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(getClass(), "TypeSystem1.xml", * "TypeSystem2.xml"); * } * } From f697932cef2569ce68a986bf570bf9af4de63f53 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Fri, 26 Aug 2022 16:40:34 +0200 Subject: [PATCH 74/94] #245 - Utility method for loading type systems in SPI providers - Fix documentation --- .../src/main/java/org/apache/uima/util/TypeSystemUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java index 75726fb537..59b9d8431a 100644 --- a/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java +++ b/uimaj-core/src/main/java/org/apache/uima/util/TypeSystemUtil.java @@ -51,7 +51,7 @@ public class TypeSystemUtil { *
    * public class MyTypeSystemDescriptionProvider implements TypeSystemDescriptionProvider {
    *   {@code @Override}
-   *   public List listTypeSystemDescriptions() {
+   *   {@code public List listTypeSystemDescriptions()} {
    *     return TypeSystemUtil.loadTypeSystemDescriptionsFromClasspath(getClass(), "TypeSystem1.xml",
    *             "TypeSystem2.xml");
    *   }

From 30c1cb9be2d36d09d468368d6b11ec25b0bcd352 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Mon, 29 Aug 2022 15:49:40 +0200
Subject: [PATCH 75/94] Issue #247 - RelativePathResolver should consider TCCL

- Consider the TCCL in the RelativePathResolver_impl
---
 jVinci/.gitignore                             |  1 +
 uimaj-adapter-vinci/.gitignore                |  1 +
 uimaj-core/.gitignore                         |  1 +
 .../impl/RelativePathResolver_impl.java       | 19 ++++++++++++-------
 uimaj-cpe/.gitignore                          |  1 +
 uimaj-tools/.gitignore                        |  1 +
 6 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/jVinci/.gitignore b/jVinci/.gitignore
index 00d2ab71dd..f837dacf90 100644
--- a/jVinci/.gitignore
+++ b/jVinci/.gitignore
@@ -1,2 +1,3 @@
 /.apt_generated/
 /.apt_generated_tests/
+/META-INF/
diff --git a/uimaj-adapter-vinci/.gitignore b/uimaj-adapter-vinci/.gitignore
index 00d2ab71dd..f837dacf90 100644
--- a/uimaj-adapter-vinci/.gitignore
+++ b/uimaj-adapter-vinci/.gitignore
@@ -1,2 +1,3 @@
 /.apt_generated/
 /.apt_generated_tests/
+/META-INF/
diff --git a/uimaj-core/.gitignore b/uimaj-core/.gitignore
index 00d2ab71dd..f837dacf90 100644
--- a/uimaj-core/.gitignore
+++ b/uimaj-core/.gitignore
@@ -1,2 +1,3 @@
 /.apt_generated/
 /.apt_generated_tests/
+/META-INF/
diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java b/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java
index 789dd25f29..55131cf209 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/impl/RelativePathResolver_impl.java
@@ -189,17 +189,22 @@ public URL resolveRelativePath(URL aRelativeUrl) {
 
     // fallback on classloader
     String f = aRelativeUrl.getFile();
-    URL absURL;
+    URL absURL = null;
     if (mClassLoader != null) {
       absURL = mClassLoader.getResource(f);
-    } else {// if no ClassLoader specified (could be the bootstrap classloader), try the system
-      // classloader
+    } 
+    
+    // fallback on TCCL
+    if (absURL == null) {
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        absURL = tccl.getResource(f);
+    }
 
-      // https://issues.apache.org/jira/browse/UIMA-5902
-      ClassLoader tccl = Thread.currentThread().getContextClassLoader();
-      absURL = (tccl != null) ? tccl.getResource(f)
-              : ClassLoader.getSystemClassLoader().getResource(f);
+    // if no ClassLoader specified (could be the bootstrap classloader), try the system classloader
+    if (absURL == null && mClassLoader == null) {
+        absURL = ClassLoader.getSystemClassLoader().getResource(f);
     }
+
     return absURL;
   }
 
diff --git a/uimaj-cpe/.gitignore b/uimaj-cpe/.gitignore
index ab858ca0ea..5f75f4ef6f 100644
--- a/uimaj-cpe/.gitignore
+++ b/uimaj-cpe/.gitignore
@@ -3,3 +3,4 @@ checkpoint_synchPoint.xml
 checkpoint_synchPoint.xml.prev
 /.apt_generated/
 /.apt_generated_tests/
+/META-INF/
diff --git a/uimaj-tools/.gitignore b/uimaj-tools/.gitignore
index 00d2ab71dd..f837dacf90 100644
--- a/uimaj-tools/.gitignore
+++ b/uimaj-tools/.gitignore
@@ -1,2 +1,3 @@
 /.apt_generated/
 /.apt_generated_tests/
+/META-INF/

From 1571bdd6c5a8329a7d4061c46dfb707fae3438db Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Mon, 29 Aug 2022 15:56:24 +0200
Subject: [PATCH 76/94] Issue #226: Provide SPI interfaces to locate
 descriptors and JCas classes

- When obtaining a MH for a lookup through a custom classloader, make sure it is a UIMAClassLoader because otherwise the MHLC magic cannot work and the JCas classes get loaded through the wrong classloader - in particular applies to SPIs in an OSGI environment
---
 .../apache/uima/cas/impl/FSClassRegistry.java | 22 ++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
index b0142d3e66..36999e48d0 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
@@ -34,6 +34,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Parameter;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -198,6 +199,8 @@ public abstract class FSClassRegistry { // abstract to prevent instantiating; th
   private static final WeakIdentityMap cl_to_type2JCasStacks;
   private static final WeakIdentityMap>> cl_to_spiJCas = WeakIdentityMap
           .newHashMap();
+  private static final WeakIdentityMap cl_to_uimaCl = WeakIdentityMap
+          .newHashMap();
 
   // private static final Map> cl_4pears_to_type2JCas =
   // Collections.synchronizedMap(new IdentityHashMap<>()); // identity: key is classloader
@@ -1749,10 +1752,27 @@ static Map get_className_to_jcci(ClassLoader cl, boolean
     }
   }
 
+  private static final URL[] NO_URLS = new URL[0];
+  
   static Lookup getLookup(ClassLoader cl) {
     Lookup lookup = null;
     try {
-      Class clazz = Class.forName(UIMAClassLoader.MHLC, true, cl);
+      // The UIMAClassLoader has special handling for the MHLC, so we must make sure that the CL
+      // we are using is actually a UIMAClassLoader, otherwise the MHCL will look up in the wrong
+      // CL. This is in particular an issue for classes loaded through the SPI mechanism.
+      UIMAClassLoader ucl;
+      if (!(cl instanceof UIMAClassLoader)) {
+        ucl = cl_to_uimaCl.get(cl);
+        if (ucl == null ) {
+          ucl = new UIMAClassLoader(NO_URLS, cl);
+          cl_to_uimaCl.put(cl, ucl);
+        }
+      } 
+      else {
+        ucl = (UIMAClassLoader) cl;
+      }
+      
+      Class clazz = Class.forName(UIMAClassLoader.MHLC, true, ucl);
       Method m = clazz.getMethod("getMethodHandlesLookup");
       lookup = (Lookup) m.invoke(null);
     } catch (ClassNotFoundException | NoSuchMethodException | SecurityException

From 647793d6c6ed91cb1bc2ed974fa73363971950cb Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Mon, 29 Aug 2022 21:50:14 +0200
Subject: [PATCH 77/94] Issue #226: Provide SPI interfaces to locate
 descriptors and JCas classes

- Synchronize access to UCL cache
---
 .../apache/uima/cas/impl/FSClassRegistry.java   | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
index 36999e48d0..4b777674e6 100644
--- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
+++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
@@ -1753,7 +1753,7 @@ static Map get_className_to_jcci(ClassLoader cl, boolean
   }
 
   private static final URL[] NO_URLS = new URL[0];
-  
+
   static Lookup getLookup(ClassLoader cl) {
     Lookup lookup = null;
     try {
@@ -1762,16 +1762,17 @@ static Lookup getLookup(ClassLoader cl) {
       // CL. This is in particular an issue for classes loaded through the SPI mechanism.
       UIMAClassLoader ucl;
       if (!(cl instanceof UIMAClassLoader)) {
-        ucl = cl_to_uimaCl.get(cl);
-        if (ucl == null ) {
-          ucl = new UIMAClassLoader(NO_URLS, cl);
-          cl_to_uimaCl.put(cl, ucl);
+        synchronized (cl_to_uimaCl) {
+          ucl = cl_to_uimaCl.get(cl);
+          if (ucl == null) {
+            ucl = new UIMAClassLoader(NO_URLS, cl);
+            cl_to_uimaCl.put(cl, ucl);
+          }
         }
-      } 
-      else {
+      } else {
         ucl = (UIMAClassLoader) cl;
       }
-      
+
       Class clazz = Class.forName(UIMAClassLoader.MHLC, true, ucl);
       Method m = clazz.getMethod("getMethodHandlesLookup");
       lookup = (Lookup) m.invoke(null);

From 4de1bd9810548cc3487c4288598ddd8a573f2d41 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Fri, 16 Sep 2022 09:42:32 +0200
Subject: [PATCH 78/94] Issue #225: Improve deployment in OSGi environments

- Turned uimaj-cpe into a fragment of uimaj-core because uimaj-core needs access to the packages of uimaj-cpe, e.g. because it accesses classes like CpeInclude via reflection in its factories
---
 uimaj-cpe/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/uimaj-cpe/pom.xml b/uimaj-cpe/pom.xml
index a23b7e2081..7c2528ac51 100644
--- a/uimaj-cpe/pom.xml
+++ b/uimaj-cpe/pom.xml
@@ -103,8 +103,8 @@
 						JavaSE-1.8
 						<_dsannotations>*
 						<_metatypeannotations>*
+						org.apache.uima.j-core
 						
-							!org.apache.uima.collection.impl.metadata.cpe,
 							!com.apple.eio,
 							org.slf4j.impl;resolution:=optional,
 							org.apache.logging.log4j.*;resolution:=optional,

From 2be73010c2f0cb99019549da2af53219f21e3a0e Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 12 Oct 2022 09:56:39 +0200
Subject: [PATCH 79/94] Issue #252: Potential failure to look up FsGenerator3
 in OSGI-like contexts

- If the class to be looked up is in the FsGenerator3 package, use the classloader of FsGenerator3
---
 .../uima/internal/util/UIMAClassLoader.java       | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/internal/util/UIMAClassLoader.java b/uimaj-core/src/main/java/org/apache/uima/internal/util/UIMAClassLoader.java
index f3c4f99afc..026351463b 100644
--- a/uimaj-core/src/main/java/org/apache/uima/internal/util/UIMAClassLoader.java
+++ b/uimaj-core/src/main/java/org/apache/uima/internal/util/UIMAClassLoader.java
@@ -29,6 +29,7 @@
 import java.util.StringTokenizer;
 
 import org.apache.uima.cas.impl.FSClassRegistry;
+import org.apache.uima.cas.impl.FsGenerator3;
 import org.apache.uima.cas.impl.TypeSystemImpl;
 
 /**
@@ -235,15 +236,23 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE
             c = findClass(name);
           }
         } catch (ClassNotFoundException e) {
-          // delegate class loading for this class-name
-          c = super.loadClass(name, false);
+          if (name.startsWith(FsGenerator3.class.getPackage().getName() + ".")) {
+            // There may be cases where the target class uses a classloader that has no access
+            // to the UIMA internal classes - in particular to the FSGenerator3 - so we force using
+            // the UIMA classloader in this case.
+            c = FsGenerator3.class.getClassLoader().loadClass(name);
+          } else {
+            // delegate class loading for this class-name
+            c = super.loadClass(name, false);
+          }
         }
       }
+
       if (resolve) {
         resolveClass(c);
       }
-      return c;
 
+      return c;
     }
   }
 

From 82067b6ccebf836414ddf9d4c935e91a1af906f4 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Fri, 14 Oct 2022 09:39:39 +0200
Subject: [PATCH 80/94] Issue #255: File handle leak accessing
 performanceTuning.properties

- Wrap access with try-with-resources
---
 .../main/java/org/apache/uima/impl/UIMAFramework_impl.java | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/impl/UIMAFramework_impl.java b/uimaj-core/src/main/java/org/apache/uima/impl/UIMAFramework_impl.java
index 3e72df30f1..2058a41aef 100644
--- a/uimaj-core/src/main/java/org/apache/uima/impl/UIMAFramework_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/impl/UIMAFramework_impl.java
@@ -21,6 +21,7 @@
 
 import java.beans.Introspector;
 import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -185,8 +186,10 @@ protected void _initialize() throws Exception {
 
     // read performance tuning properties
     mDefaultPerformanceTuningProperties = new Properties();
-    mDefaultPerformanceTuningProperties
-            .load(UIMAFramework_impl.class.getResourceAsStream("performanceTuning.properties"));
+    try (InputStream is = UIMAFramework_impl.class
+            .getResourceAsStream("performanceTuning.properties")) {
+      mDefaultPerformanceTuningProperties.load(is);
+    }
 
     // create new HashMap for the LogWrappers
     mLoggers = new ConcurrentHashMap<>(200, 1.0f);

From 6870f8dab5354344162e2783f7547dcf49d9eb39 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Mon, 17 Oct 2022 17:50:59 +0200
Subject: [PATCH 81/94] Issue #258: Apache UIMA Java SDK 3.3.1 release

- Update RELEASE.md
---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 62f31d201c..15992bffc6 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,7 @@ to your project:
 
   org.apache.uima
   uimaj-core
-  3.3.0
+  3.3.1
 
 ```
 
@@ -55,7 +55,7 @@ Apache uimaFIT is a separate dependency that you can add:
 
   org.apache.uima
   uimafit-core
-  3.3.0
+  3.3.1
 
 ```
 

From 14ca7bb0784f5497cac90c40ab8f549f656040c0 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Mon, 17 Oct 2022 18:00:06 +0200
Subject: [PATCH 82/94] Issue #258: Apache UIMA Java SDK 3.3.1 release

- Update RELEASE_NOTES.md
---
 RELEASE_NOTES.md | 64 ++++++++++++++++--------------------------------
 1 file changed, 21 insertions(+), 43 deletions(-)

diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 7a168e0f15..abed3dab7a 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -19,7 +19,7 @@
 ***************************************************************
 -->
    
-# Apache UIMA (Unstructured Information Management Architecture) v3.3.0 Release Notes
+# Apache UIMA (Unstructured Information Management Architecture) v3.3.1 Release Notes
 
 ## Contents
 
@@ -55,46 +55,24 @@ with some support for Perl, Python and TCL.
 
 ## Notable changes in this release
 
-* [UIMA-6418] Added support for component parameters of type "long" and "double" 
-* [UIMA-6358] Added platform-independent methods for setting the datapath in a resource manager
-* [UIMA-6374] Added an extensive CAS (de)serialization test suit
-* [UIMA-6431] Added support for using lambda functions as CAS processors
-* [UIMA-6412] Changed CPMEngine from using a thread group to using an executor service
-* [UIMA-6389] Fixed exceptions being swallowed when using Log4J2 through its SLF4J API
-* [UIMA-6386] Fixed wrong UIMA session being set on the ConfigurationManager in aggregates
-* [UIMA-6390] Fixed NPE when trying to access config names of fresh context
-* [UIMA-6378] Fixed build on Java 16
-* [UIMA-6393] Fixed circular imports in descriptors breaking the resource manager cache
-* [UIMA-6367] Fixed JCas cover annotation created in PEAR context being replaced by index operations
-* [UIMA-6388] Fixed CAS.select(null) returning all annotations instead of throwing an exception
-* [UIMA-6423] Fixed selecting a non-existing type returning all types instead of throwing an exception
-* [UIMA-6421] Fixed range check when injecting a String value into StringArray slot to throw an exception
-* [UIMA-6400] Fixed leaking ThreadLocal in UimaContextHolder
-* [UIMA-6398] Fixed memory leak in UIMA loggers and loggers using the wrong classloader for i18n messages
-* [UIMA-6413] Fixed memory leak in FSClassRegistry
-* [UIMA-6377] Fixed spurious multipleReferencesAllowed warning when serializing empty arrays
-* [UIMA-6372] Upgraded to JUnit 5
-* [UIMA-6373] Format UIMA Core Java SDK codebase
-
-### API changes
-
-#### SelectFS API with null or non-existing types
-
-When providing `null` or as a type or an non-existing type to a `select` call, then an exception is
-is thrown. Previously, all annotations were returned instead. To explicitly select any type, use
-the new `anyType()` instead of calling `type(null)`.
-
-#### ResourceManager datapath methods
-
-The methods `getDataPath()` and `setDataPath(String)` which were accepting/returning paths using 
-platform-specific path separators have been deprepcated. Instead, use the new 
-`setDataPathElements(File/String...)` and `getDataPathElements()` methods.
-
-#### JUnit upgrade
-
-The JUnit module has been upgraded from JUnit 4 to JUnit 5 along with the rest of the test code
-switching to JUnit 5. If you use the unit test helpers from this module, you also have to upgrade
-your tests to JUnit 5.
+This is a bug fix release.
+
+**Bugs fixed**
+* 🦟 Issue #255: File handle leak accessing performanceTuning.properties
+* 🦟 Issue #240: Helper annotation created by SelectFS should not survive
+* 🦟 Issue #238: Form 6 serializes non-reachable FSes but should not
+* 🦟 Issue #235: Misleading error message when JCas type is not registered
+* 🦟 [UIMA-6479] PearPackagingMavenPlugin has ancient JUnit dependency
+* 🦟 [UIMA-6473] CasToComparableText is broken
+
+**Improvements**
+* ⭐️ Issue #222: Support comparing test files irrespective of line endings
+* ⭐️ [UIMA-6480] Add tests with empty arrays to CAS de/ser-suite
+
+**Refactoring**
+* ⚙️ [UIMA-6454] Update dependencies
+* ⚙️ [UIMA-6463] Use toolchains to ensure compatibility with Java 1.8
+* ⚙️ [UIMA-6469] Cleaning up file handling code
 
 ## Full list of JIRA Issues affecting this Release
 
@@ -111,5 +89,5 @@ help, source code and feedback. If you are interested in contributing, please vi
 
 ## How to Report Issues
 
-The Apache UIMA project uses JIRA for issue tracking. Please report any issues you find at 
-[http://issues.apache.org/jira/browse/uima](http://issues.apache.org/jira/browse/uima).
\ No newline at end of file
+The Apache UIMA project uses GitHub for issue tracking. Please report any issues you find at 
+[https://github.com/apache/uima-uimaj/issues](https://github.com/apache/uima-uimaj/issues).
\ No newline at end of file

From 1ee4d59f15c12fb2ead98f1629160d4df5890489 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Mon, 17 Oct 2022 18:05:30 +0200
Subject: [PATCH 83/94] Issue #258: Apache UIMA Java SDK 3.3.1 release

- Update RELEASE_NOTES.md
---
 RELEASE_NOTES.md | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index abed3dab7a..4618d79676 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -74,12 +74,10 @@ This is a bug fix release.
 * ⚙️ [UIMA-6463] Use toolchains to ensure compatibility with Java 1.8
 * ⚙️ [UIMA-6469] Cleaning up file handling code
 
-## Full list of JIRA Issues affecting this Release
+For a full list of issues affecting this release, please see:
 
-Click [issuesFixed/jira-report.hmtl](issuesFixed/jira-report.html) for the list of issues affecting
-this release.
-
-Please use the mailing lists ( http://uima.apache.org/mail-lists.html ) for feedback.
+* https://github.com/apache/uima-uimaj/issues?q=milestone%3A3.3.1
+* https://issues.apache.org/jira/issues/?jql=project%20%3D%20UIMA%20AND%20fixVersion%20%3D%203.3.1SDK
 
 ## How to Get Involved
 

From 2ab21b6dd08a8a405d6374441fc347af77055fd3 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 19 Oct 2022 10:14:12 +0200
Subject: [PATCH 84/94] Issue #260: Issues-fixed report for GitHub and Jira

- Switch the configuration for the issues report in the main POM from Jira to GitHub and set GitHub as the new main issue management system
- Add a non-deployed module to also generate a report from issues that we still have on Jira
---
 pom.xml                          | 15 +++++--
 uimaj-legacy-jira-report/pom.xml | 73 ++++++++++++++++++++++++++++++++
 uimaj-parent/pom.xml             |  6 +++
 3 files changed, 90 insertions(+), 4 deletions(-)
 create mode 100644 uimaj-legacy-jira-report/pom.xml

diff --git a/pom.xml b/pom.xml
index 8817b9cb93..2d11cd77b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,7 +40,6 @@
   ${uimaWebsiteUrl}
 
   
-    3.3.0SDK   
     uimaj-${project.version} 
     src/main/assembly/bin-without-jackson.xml 
     ${ibmNoticeText}    
@@ -191,6 +190,7 @@
   
     uimaj-parent
     aggregate-uimaj
+    uimaj-legacy-jira-report
   
   
   
@@ -342,13 +342,20 @@
             
               
                 default-cli
+                generate-resources
+                
+                  github-report
+                
                 
-                  ${jiraVersion}
+                  Type,Id,Status,Summary
+                  true
+                  https
+                  443
                 
               
-              
+            
           
-             
+        
       
     
     
diff --git a/uimaj-legacy-jira-report/pom.xml b/uimaj-legacy-jira-report/pom.xml
new file mode 100644
index 0000000000..48ea2b8afa
--- /dev/null
+++ b/uimaj-legacy-jira-report/pom.xml
@@ -0,0 +1,73 @@
+
+
+
+  4.0.0
+
+  
+    org.apache.uima
+    uimaj-parent
+    3.3.1-SNAPSHOT
+    ../uimaj-parent/pom.xml
+  
+
+  uimaj-legacy-jira-report
+  pom
+
+  
+    3.3.1SDK
+    true
+  
+
+  
+    Jira
+    https://issues.apache.org/jira/browse/UIMA
+  
+
+  
+    
+      apache-release
+      
+        
+        
+        
+          
+            maven-changes-plugin
+            
+              
+                default-cli
+                generate-resources
+                
+                  jira-report
+                
+                
+                  Type,Key,Status,Summary
+                  ${project.basedir}/../issuesFixed
+                  ${jiraVersion}
+                
+              
+            
+          
+        
+      
+    
+  
+
diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml
index eff05a5ad0..7c65739a33 100644
--- a/uimaj-parent/pom.xml
+++ b/uimaj-parent/pom.xml
@@ -44,6 +44,11 @@
   The common parent pom for the UIMA Java SDK
   ${uimaWebsiteUrl}
 
+  
+    Github
+    https://github.com/apache/uima-uimaj/issues
+  
+
   
     uimaj-3.2.0
     scm:git:https://github.com/apache/uima-uimaj/
@@ -142,6 +147,7 @@
     5.8.2
     3.22.0
     2.9.0
+    3.2.5
 
     1.8
     1.8

From f337a1d480c1ebc40031e40cd7ed76cae0a3dd07 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 19 Oct 2022 10:21:04 +0200
Subject: [PATCH 85/94] Issue #258: Apache UIMA Java SDK 3.3.1 release

- Update API comparison version in POM
---
 uimaj-parent/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml
index eff05a5ad0..4f809f8ef5 100644
--- a/uimaj-parent/pom.xml
+++ b/uimaj-parent/pom.xml
@@ -148,7 +148,7 @@
 
     org.eclipse.p2.201812
 
-    3.2.0
+    3.3.0
   
 
   

From 45394a48d99899b77306d3c298028fc7c6d6cdb7 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 19 Oct 2022 10:25:38 +0200
Subject: [PATCH 86/94] Issue #258: Apache UIMA Java SDK 3.3.1 release

- Update the version in the uimaj-eclipse-update-site
---
 uimaj-eclipse-update-site/pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/uimaj-eclipse-update-site/pom.xml b/uimaj-eclipse-update-site/pom.xml
index cc0e8b3a69..734620ba80 100644
--- a/uimaj-eclipse-update-site/pom.xml
+++ b/uimaj-eclipse-update-site/pom.xml
@@ -25,12 +25,12 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.0
+    3.3.1
     
   
 
   uimaj-eclipse-update-site
-  3.3.0
+  3.3.1
   pom
 
   Apache UIMA Eclipse: ${project.artifactId}

From 43009174482e6648f9ddbe6a6914fafb85f5e6ff Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 19 Oct 2022 10:30:24 +0200
Subject: [PATCH 87/94] Issue #258: Apache UIMA Java SDK 3.3.1 release

- Update RELEASE_NOTES.md
---
 RELEASE_NOTES.md | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 4618d79676..06bba2e249 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -27,7 +27,6 @@
 [Major Changes in this Release](#major.changes)  
 [How to Get Involved](#get.involved)  
 [How to Report Issues](#report.issues)  
-[List of JIRA Issues Fixed in this Release](#list.issues)  
 
 ## What is UIMA?
 
@@ -76,8 +75,8 @@ This is a bug fix release.
 
 For a full list of issues affecting this release, please see:
 
-* https://github.com/apache/uima-uimaj/issues?q=milestone%3A3.3.1
-* https://issues.apache.org/jira/issues/?jql=project%20%3D%20UIMA%20AND%20fixVersion%20%3D%203.3.1SDK
+* [GitHub issues](issuesFixed/github-report.html) [[online](https://github.com/apache/uima-uimaj/issues?q=milestone%3A3.3.1)]
+* [Jira issues (legacy)](issuesFixed/jira-report.html) [[online](https://issues.apache.org/jira/issues/?jql=project%20%3D%20UIMA%20AND%20fixVersion%20%3D%203.3.1SDK)]
 
 ## How to Get Involved
 

From b6528674b2fb50396073ef60a5f588fd096470f5 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 19 Oct 2022 14:00:03 +0200
Subject: [PATCH 88/94] [maven-release-plugin] prepare release uimaj-3.3.1

---
 PearPackagingMavenPlugin/pom.xml                | 6 ++----
 aggregate-uimaj-docbooks/pom.xml                | 2 +-
 aggregate-uimaj-eclipse-plugins/pom.xml         | 2 +-
 aggregate-uimaj/pom.xml                         | 2 +-
 jVinci/pom.xml                                  | 2 +-
 jcasgen-maven-plugin/pom.xml                    | 6 ++----
 pom.xml                                         | 4 ++--
 uima-doc-v3-users-guide/pom.xml                 | 2 +-
 uima-docbook-overview-and-setup/pom.xml         | 2 +-
 uima-docbook-references/pom.xml                 | 2 +-
 uima-docbook-tools/pom.xml                      | 2 +-
 uima-docbook-tutorials-and-users-guides/pom.xml | 2 +-
 uimaj-adapter-vinci/pom.xml                     | 2 +-
 uimaj-bootstrap/pom.xml                         | 2 +-
 uimaj-component-test-util/pom.xml               | 2 +-
 uimaj-core/pom.xml                              | 2 +-
 uimaj-cpe/pom.xml                               | 2 +-
 uimaj-document-annotation/pom.xml               | 2 +-
 uimaj-eclipse-feature-runtime/pom.xml           | 2 +-
 uimaj-eclipse-feature-tools/pom.xml             | 2 +-
 uimaj-ep-cas-editor-ide/pom.xml                 | 2 +-
 uimaj-ep-cas-editor/pom.xml                     | 2 +-
 uimaj-ep-configurator/pom.xml                   | 2 +-
 uimaj-ep-debug/pom.xml                          | 2 +-
 uimaj-ep-jcasgen/pom.xml                        | 2 +-
 uimaj-ep-launcher/pom.xml                       | 2 +-
 uimaj-ep-pear-packager/pom.xml                  | 2 +-
 uimaj-ep-runtime/pom.xml                        | 2 +-
 uimaj-examples/pom.xml                          | 2 +-
 uimaj-json/pom.xml                              | 2 +-
 uimaj-legacy-jira-report/pom.xml                | 6 ++----
 uimaj-parent/pom.xml                            | 8 +++-----
 uimaj-test-util/pom.xml                         | 2 +-
 uimaj-tools/pom.xml                             | 2 +-
 uimaj-v3migration-jcas/pom.xml                  | 2 +-
 35 files changed, 41 insertions(+), 49 deletions(-)

diff --git a/PearPackagingMavenPlugin/pom.xml b/PearPackagingMavenPlugin/pom.xml
index 3c59cce932..c33ec98987 100644
--- a/PearPackagingMavenPlugin/pom.xml
+++ b/PearPackagingMavenPlugin/pom.xml
@@ -17,15 +17,13 @@
    specific language governing permissions and limitations
    under the License.    
 -->
-
+
   4.0.0
 
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/aggregate-uimaj-docbooks/pom.xml b/aggregate-uimaj-docbooks/pom.xml
index c0ce1233d0..86531f2a73 100644
--- a/aggregate-uimaj-docbooks/pom.xml
+++ b/aggregate-uimaj-docbooks/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/aggregate-uimaj-eclipse-plugins/pom.xml b/aggregate-uimaj-eclipse-plugins/pom.xml
index d87f72db59..57220c2514 100644
--- a/aggregate-uimaj-eclipse-plugins/pom.xml
+++ b/aggregate-uimaj-eclipse-plugins/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/aggregate-uimaj/pom.xml b/aggregate-uimaj/pom.xml
index 22ab7d25cf..85f9b8d3a8 100644
--- a/aggregate-uimaj/pom.xml
+++ b/aggregate-uimaj/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/jVinci/pom.xml b/jVinci/pom.xml
index 3a74f5bba2..004c686b09 100644
--- a/jVinci/pom.xml
+++ b/jVinci/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/jcasgen-maven-plugin/pom.xml b/jcasgen-maven-plugin/pom.xml
index c0f1d4690f..b0084063b1 100644
--- a/jcasgen-maven-plugin/pom.xml
+++ b/jcasgen-maven-plugin/pom.xml
@@ -16,14 +16,12 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-
+
   4.0.0
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
   
diff --git a/pom.xml b/pom.xml
index 2d11cd77b2..2089f88e95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     uimaj-parent/pom.xml
   
 
@@ -49,7 +49,7 @@
     scm:git:https://github.com/apache/uima-uimaj/
     scm:git:https://github.com/apache/uima-uimaj/
     https://github.com/apache/uima-uimaj/
-    uimaj-3.2.0
+    uimaj-3.3.1
   
 
   
diff --git a/uima-doc-v3-users-guide/pom.xml b/uima-doc-v3-users-guide/pom.xml
index f91d3c255e..94f0612d4e 100644
--- a/uima-doc-v3-users-guide/pom.xml
+++ b/uima-doc-v3-users-guide/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uima-docbook-overview-and-setup/pom.xml b/uima-docbook-overview-and-setup/pom.xml
index 893f920114..a53dbe1c3d 100644
--- a/uima-docbook-overview-and-setup/pom.xml
+++ b/uima-docbook-overview-and-setup/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
   
diff --git a/uima-docbook-references/pom.xml b/uima-docbook-references/pom.xml
index 8dee4bc50a..7d36c04f54 100644
--- a/uima-docbook-references/pom.xml
+++ b/uima-docbook-references/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uima-docbook-tools/pom.xml b/uima-docbook-tools/pom.xml
index 159a71a260..a7785db4c1 100644
--- a/uima-docbook-tools/pom.xml
+++ b/uima-docbook-tools/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uima-docbook-tutorials-and-users-guides/pom.xml b/uima-docbook-tutorials-and-users-guides/pom.xml
index f562252669..cfcf3ffa0a 100644
--- a/uima-docbook-tutorials-and-users-guides/pom.xml
+++ b/uima-docbook-tutorials-and-users-guides/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-adapter-vinci/pom.xml b/uimaj-adapter-vinci/pom.xml
index e6a69ee1ed..dedc9d3db7 100644
--- a/uimaj-adapter-vinci/pom.xml
+++ b/uimaj-adapter-vinci/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-bootstrap/pom.xml b/uimaj-bootstrap/pom.xml
index 46d1f665f8..e224803597 100644
--- a/uimaj-bootstrap/pom.xml
+++ b/uimaj-bootstrap/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-component-test-util/pom.xml b/uimaj-component-test-util/pom.xml
index ac26831183..8344e22f11 100644
--- a/uimaj-component-test-util/pom.xml
+++ b/uimaj-component-test-util/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml
index 47c772b4d4..7e3364df99 100644
--- a/uimaj-core/pom.xml
+++ b/uimaj-core/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-cpe/pom.xml b/uimaj-cpe/pom.xml
index b72977baae..0b62bcacc1 100644
--- a/uimaj-cpe/pom.xml
+++ b/uimaj-cpe/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-document-annotation/pom.xml b/uimaj-document-annotation/pom.xml
index f28eb773b4..2a322366ba 100644
--- a/uimaj-document-annotation/pom.xml
+++ b/uimaj-document-annotation/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-eclipse-feature-runtime/pom.xml b/uimaj-eclipse-feature-runtime/pom.xml
index 83824ec1bf..736a12fb8e 100644
--- a/uimaj-eclipse-feature-runtime/pom.xml
+++ b/uimaj-eclipse-feature-runtime/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-eclipse-feature-tools/pom.xml b/uimaj-eclipse-feature-tools/pom.xml
index 86834546bd..89b868691f 100644
--- a/uimaj-eclipse-feature-tools/pom.xml
+++ b/uimaj-eclipse-feature-tools/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-cas-editor-ide/pom.xml b/uimaj-ep-cas-editor-ide/pom.xml
index fa9ccf814f..f56afd479b 100644
--- a/uimaj-ep-cas-editor-ide/pom.xml
+++ b/uimaj-ep-cas-editor-ide/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-cas-editor/pom.xml b/uimaj-ep-cas-editor/pom.xml
index c0d4b9011e..779506d60b 100644
--- a/uimaj-ep-cas-editor/pom.xml
+++ b/uimaj-ep-cas-editor/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-configurator/pom.xml b/uimaj-ep-configurator/pom.xml
index 7de51a5d88..ca283e103c 100644
--- a/uimaj-ep-configurator/pom.xml
+++ b/uimaj-ep-configurator/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-debug/pom.xml b/uimaj-ep-debug/pom.xml
index 899b12e279..ec6cc738ae 100644
--- a/uimaj-ep-debug/pom.xml
+++ b/uimaj-ep-debug/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-jcasgen/pom.xml b/uimaj-ep-jcasgen/pom.xml
index 2b2644969a..73f6cbb8c7 100644
--- a/uimaj-ep-jcasgen/pom.xml
+++ b/uimaj-ep-jcasgen/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-launcher/pom.xml b/uimaj-ep-launcher/pom.xml
index 12d5444470..a729d00afd 100644
--- a/uimaj-ep-launcher/pom.xml
+++ b/uimaj-ep-launcher/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-pear-packager/pom.xml b/uimaj-ep-pear-packager/pom.xml
index ec56539d40..75cc2a6167 100644
--- a/uimaj-ep-pear-packager/pom.xml
+++ b/uimaj-ep-pear-packager/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-runtime/pom.xml b/uimaj-ep-runtime/pom.xml
index 36e9c93b6f..1223981629 100644
--- a/uimaj-ep-runtime/pom.xml
+++ b/uimaj-ep-runtime/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-examples/pom.xml b/uimaj-examples/pom.xml
index fbcdd4db04..8257504642 100644
--- a/uimaj-examples/pom.xml
+++ b/uimaj-examples/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-json/pom.xml b/uimaj-json/pom.xml
index 35487810c2..cf7aac0f03 100644
--- a/uimaj-json/pom.xml
+++ b/uimaj-json/pom.xml
@@ -22,7 +22,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
   uimaj-json
diff --git a/uimaj-legacy-jira-report/pom.xml b/uimaj-legacy-jira-report/pom.xml
index 48ea2b8afa..e3d8bad6d9 100644
--- a/uimaj-legacy-jira-report/pom.xml
+++ b/uimaj-legacy-jira-report/pom.xml
@@ -17,15 +17,13 @@
    specific language governing permissions and limitations
    under the License.
 -->
-
+
   4.0.0
 
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml
index a089418c3c..b6f40d91a9 100644
--- a/uimaj-parent/pom.xml
+++ b/uimaj-parent/pom.xml
@@ -25,9 +25,7 @@
      project-wide parent pom.
  -->
 
-
+
   4.0.0
 
   
@@ -39,7 +37,7 @@
 
   uimaj-parent
   pom
-  3.3.1-SNAPSHOT
+  3.3.1
   Apache UIMA Java SDK: ${project.artifactId}
   The common parent pom for the UIMA Java SDK
   ${uimaWebsiteUrl}
@@ -50,7 +48,7 @@
   
 
   
-    uimaj-3.2.0
+    uimaj-3.3.1
     scm:git:https://github.com/apache/uima-uimaj/
     scm:git:https://github.com/apache/uima-uimaj/
     https://github.com/apache/uima-uimaj/
diff --git a/uimaj-test-util/pom.xml b/uimaj-test-util/pom.xml
index 910f9cd5b5..fd8a7e8c9e 100644
--- a/uimaj-test-util/pom.xml
+++ b/uimaj-test-util/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-tools/pom.xml b/uimaj-tools/pom.xml
index be54547301..5447ddd53a 100644
--- a/uimaj-tools/pom.xml
+++ b/uimaj-tools/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-v3migration-jcas/pom.xml b/uimaj-v3migration-jcas/pom.xml
index a6b0775844..5e96eda610 100644
--- a/uimaj-v3migration-jcas/pom.xml
+++ b/uimaj-v3migration-jcas/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.3.1
     ../uimaj-parent/pom.xml
   
 

From 5bb5523636f6559d9e7d1e7c5b4840fe10fae09c Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 19 Oct 2022 14:00:08 +0200
Subject: [PATCH 89/94] [maven-release-plugin] prepare for next development
 iteration

---
 PearPackagingMavenPlugin/pom.xml                | 2 +-
 aggregate-uimaj-docbooks/pom.xml                | 2 +-
 aggregate-uimaj-eclipse-plugins/pom.xml         | 2 +-
 aggregate-uimaj/pom.xml                         | 2 +-
 jVinci/pom.xml                                  | 2 +-
 jcasgen-maven-plugin/pom.xml                    | 2 +-
 pom.xml                                         | 4 ++--
 uima-doc-v3-users-guide/pom.xml                 | 2 +-
 uima-docbook-overview-and-setup/pom.xml         | 2 +-
 uima-docbook-references/pom.xml                 | 2 +-
 uima-docbook-tools/pom.xml                      | 2 +-
 uima-docbook-tutorials-and-users-guides/pom.xml | 2 +-
 uimaj-adapter-vinci/pom.xml                     | 2 +-
 uimaj-bootstrap/pom.xml                         | 2 +-
 uimaj-component-test-util/pom.xml               | 2 +-
 uimaj-core/pom.xml                              | 2 +-
 uimaj-cpe/pom.xml                               | 2 +-
 uimaj-document-annotation/pom.xml               | 2 +-
 uimaj-eclipse-feature-runtime/pom.xml           | 2 +-
 uimaj-eclipse-feature-tools/pom.xml             | 2 +-
 uimaj-ep-cas-editor-ide/pom.xml                 | 2 +-
 uimaj-ep-cas-editor/pom.xml                     | 2 +-
 uimaj-ep-configurator/pom.xml                   | 2 +-
 uimaj-ep-debug/pom.xml                          | 2 +-
 uimaj-ep-jcasgen/pom.xml                        | 2 +-
 uimaj-ep-launcher/pom.xml                       | 2 +-
 uimaj-ep-pear-packager/pom.xml                  | 2 +-
 uimaj-ep-runtime/pom.xml                        | 2 +-
 uimaj-examples/pom.xml                          | 2 +-
 uimaj-json/pom.xml                              | 2 +-
 uimaj-legacy-jira-report/pom.xml                | 2 +-
 uimaj-parent/pom.xml                            | 4 ++--
 uimaj-test-util/pom.xml                         | 2 +-
 uimaj-tools/pom.xml                             | 2 +-
 uimaj-v3migration-jcas/pom.xml                  | 2 +-
 35 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/PearPackagingMavenPlugin/pom.xml b/PearPackagingMavenPlugin/pom.xml
index c33ec98987..5328912040 100644
--- a/PearPackagingMavenPlugin/pom.xml
+++ b/PearPackagingMavenPlugin/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/aggregate-uimaj-docbooks/pom.xml b/aggregate-uimaj-docbooks/pom.xml
index 86531f2a73..a2e1519649 100644
--- a/aggregate-uimaj-docbooks/pom.xml
+++ b/aggregate-uimaj-docbooks/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/aggregate-uimaj-eclipse-plugins/pom.xml b/aggregate-uimaj-eclipse-plugins/pom.xml
index 57220c2514..da9b1832c7 100644
--- a/aggregate-uimaj-eclipse-plugins/pom.xml
+++ b/aggregate-uimaj-eclipse-plugins/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/aggregate-uimaj/pom.xml b/aggregate-uimaj/pom.xml
index 85f9b8d3a8..6343cb8f57 100644
--- a/aggregate-uimaj/pom.xml
+++ b/aggregate-uimaj/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/jVinci/pom.xml b/jVinci/pom.xml
index 004c686b09..9aa5124d04 100644
--- a/jVinci/pom.xml
+++ b/jVinci/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/jcasgen-maven-plugin/pom.xml b/jcasgen-maven-plugin/pom.xml
index b0084063b1..a46976fd58 100644
--- a/jcasgen-maven-plugin/pom.xml
+++ b/jcasgen-maven-plugin/pom.xml
@@ -21,7 +21,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
   
diff --git a/pom.xml b/pom.xml
index 2089f88e95..6d5ecb904b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     uimaj-parent/pom.xml
   
 
@@ -49,7 +49,7 @@
     scm:git:https://github.com/apache/uima-uimaj/
     scm:git:https://github.com/apache/uima-uimaj/
     https://github.com/apache/uima-uimaj/
-    uimaj-3.3.1
+    uimaj-3.2.0
   
 
   
diff --git a/uima-doc-v3-users-guide/pom.xml b/uima-doc-v3-users-guide/pom.xml
index 94f0612d4e..cd00f390f1 100644
--- a/uima-doc-v3-users-guide/pom.xml
+++ b/uima-doc-v3-users-guide/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uima-docbook-overview-and-setup/pom.xml b/uima-docbook-overview-and-setup/pom.xml
index a53dbe1c3d..2fdec9084a 100644
--- a/uima-docbook-overview-and-setup/pom.xml
+++ b/uima-docbook-overview-and-setup/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
   
diff --git a/uima-docbook-references/pom.xml b/uima-docbook-references/pom.xml
index 7d36c04f54..9eef50fe14 100644
--- a/uima-docbook-references/pom.xml
+++ b/uima-docbook-references/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uima-docbook-tools/pom.xml b/uima-docbook-tools/pom.xml
index a7785db4c1..82250aa080 100644
--- a/uima-docbook-tools/pom.xml
+++ b/uima-docbook-tools/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uima-docbook-tutorials-and-users-guides/pom.xml b/uima-docbook-tutorials-and-users-guides/pom.xml
index cfcf3ffa0a..7b3917298d 100644
--- a/uima-docbook-tutorials-and-users-guides/pom.xml
+++ b/uima-docbook-tutorials-and-users-guides/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-adapter-vinci/pom.xml b/uimaj-adapter-vinci/pom.xml
index dedc9d3db7..7e58883f33 100644
--- a/uimaj-adapter-vinci/pom.xml
+++ b/uimaj-adapter-vinci/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-bootstrap/pom.xml b/uimaj-bootstrap/pom.xml
index e224803597..673e8937b6 100644
--- a/uimaj-bootstrap/pom.xml
+++ b/uimaj-bootstrap/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-component-test-util/pom.xml b/uimaj-component-test-util/pom.xml
index 8344e22f11..cb09cbd7c4 100644
--- a/uimaj-component-test-util/pom.xml
+++ b/uimaj-component-test-util/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-core/pom.xml b/uimaj-core/pom.xml
index 7e3364df99..a39ebf3197 100644
--- a/uimaj-core/pom.xml
+++ b/uimaj-core/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-cpe/pom.xml b/uimaj-cpe/pom.xml
index 0b62bcacc1..05ff721011 100644
--- a/uimaj-cpe/pom.xml
+++ b/uimaj-cpe/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-document-annotation/pom.xml b/uimaj-document-annotation/pom.xml
index 2a322366ba..48594b4207 100644
--- a/uimaj-document-annotation/pom.xml
+++ b/uimaj-document-annotation/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-eclipse-feature-runtime/pom.xml b/uimaj-eclipse-feature-runtime/pom.xml
index 736a12fb8e..005042d689 100644
--- a/uimaj-eclipse-feature-runtime/pom.xml
+++ b/uimaj-eclipse-feature-runtime/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-eclipse-feature-tools/pom.xml b/uimaj-eclipse-feature-tools/pom.xml
index 89b868691f..c14d4de252 100644
--- a/uimaj-eclipse-feature-tools/pom.xml
+++ b/uimaj-eclipse-feature-tools/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-cas-editor-ide/pom.xml b/uimaj-ep-cas-editor-ide/pom.xml
index f56afd479b..b7bcdb9ec3 100644
--- a/uimaj-ep-cas-editor-ide/pom.xml
+++ b/uimaj-ep-cas-editor-ide/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-cas-editor/pom.xml b/uimaj-ep-cas-editor/pom.xml
index 779506d60b..b61d64b6f6 100644
--- a/uimaj-ep-cas-editor/pom.xml
+++ b/uimaj-ep-cas-editor/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-configurator/pom.xml b/uimaj-ep-configurator/pom.xml
index ca283e103c..f045b36175 100644
--- a/uimaj-ep-configurator/pom.xml
+++ b/uimaj-ep-configurator/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-debug/pom.xml b/uimaj-ep-debug/pom.xml
index ec6cc738ae..72a1609e18 100644
--- a/uimaj-ep-debug/pom.xml
+++ b/uimaj-ep-debug/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-jcasgen/pom.xml b/uimaj-ep-jcasgen/pom.xml
index 73f6cbb8c7..019b669fe7 100644
--- a/uimaj-ep-jcasgen/pom.xml
+++ b/uimaj-ep-jcasgen/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-launcher/pom.xml b/uimaj-ep-launcher/pom.xml
index a729d00afd..76915ebccc 100644
--- a/uimaj-ep-launcher/pom.xml
+++ b/uimaj-ep-launcher/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-pear-packager/pom.xml b/uimaj-ep-pear-packager/pom.xml
index 75cc2a6167..226d83ab0a 100644
--- a/uimaj-ep-pear-packager/pom.xml
+++ b/uimaj-ep-pear-packager/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-ep-runtime/pom.xml b/uimaj-ep-runtime/pom.xml
index 1223981629..51b542126d 100644
--- a/uimaj-ep-runtime/pom.xml
+++ b/uimaj-ep-runtime/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-examples/pom.xml b/uimaj-examples/pom.xml
index 8257504642..7de9102494 100644
--- a/uimaj-examples/pom.xml
+++ b/uimaj-examples/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-json/pom.xml b/uimaj-json/pom.xml
index cf7aac0f03..4dfc0c73c4 100644
--- a/uimaj-json/pom.xml
+++ b/uimaj-json/pom.xml
@@ -22,7 +22,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
   uimaj-json
diff --git a/uimaj-legacy-jira-report/pom.xml b/uimaj-legacy-jira-report/pom.xml
index e3d8bad6d9..7daa5edf4e 100644
--- a/uimaj-legacy-jira-report/pom.xml
+++ b/uimaj-legacy-jira-report/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml
index b6f40d91a9..6e3baf71c4 100644
--- a/uimaj-parent/pom.xml
+++ b/uimaj-parent/pom.xml
@@ -37,7 +37,7 @@
 
   uimaj-parent
   pom
-  3.3.1
+  3.3.2-SNAPSHOT
   Apache UIMA Java SDK: ${project.artifactId}
   The common parent pom for the UIMA Java SDK
   ${uimaWebsiteUrl}
@@ -48,7 +48,7 @@
   
 
   
-    uimaj-3.3.1
+    uimaj-3.2.0
     scm:git:https://github.com/apache/uima-uimaj/
     scm:git:https://github.com/apache/uima-uimaj/
     https://github.com/apache/uima-uimaj/
diff --git a/uimaj-test-util/pom.xml b/uimaj-test-util/pom.xml
index fd8a7e8c9e..7cdf0813d3 100644
--- a/uimaj-test-util/pom.xml
+++ b/uimaj-test-util/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-tools/pom.xml b/uimaj-tools/pom.xml
index 5447ddd53a..abac707c10 100644
--- a/uimaj-tools/pom.xml
+++ b/uimaj-tools/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
diff --git a/uimaj-v3migration-jcas/pom.xml b/uimaj-v3migration-jcas/pom.xml
index 5e96eda610..0d37f38f07 100644
--- a/uimaj-v3migration-jcas/pom.xml
+++ b/uimaj-v3migration-jcas/pom.xml
@@ -23,7 +23,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1
+    3.3.2-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 

From 945240bfbdee4178cdfb3af71de7db5cc453444d Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Thu, 24 Nov 2022 16:52:06 +0100
Subject: [PATCH 90/94] No issue. Adjust jira legacy module version.

---
 uimaj-legacy-jira-report/pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/uimaj-legacy-jira-report/pom.xml b/uimaj-legacy-jira-report/pom.xml
index 48ea2b8afa..c04be281fd 100644
--- a/uimaj-legacy-jira-report/pom.xml
+++ b/uimaj-legacy-jira-report/pom.xml
@@ -25,7 +25,7 @@
   
     org.apache.uima
     uimaj-parent
-    3.3.1-SNAPSHOT
+    3.4.0-SNAPSHOT
     ../uimaj-parent/pom.xml
   
 
@@ -33,7 +33,7 @@
   pom
 
   
-    3.3.1SDK
+    3.4.0SDK
     true
   
 

From c98e9c4c425e6f47de110d8b635156a40f6f24d7 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 7 Dec 2022 09:51:24 +0100
Subject: [PATCH 91/94] #267 - UIMA Log4jLogger_impl not compatible with log4j
 2.18.0+

- Use reflection to pry-open a protected class that was previously public - frankly, this is not a good solution...
---
 .../uima/util/impl/Log4jLogger_impl.java      | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/util/impl/Log4jLogger_impl.java b/uimaj-core/src/main/java/org/apache/uima/util/impl/Log4jLogger_impl.java
index 1881df81ad..7b6dd09c03 100644
--- a/uimaj-core/src/main/java/org/apache/uima/util/impl/Log4jLogger_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/util/impl/Log4jLogger_impl.java
@@ -18,6 +18,7 @@
  */
 package org.apache.uima.util.impl;
 
+import java.lang.reflect.Field;
 import java.text.MessageFormat;
 
 import org.apache.logging.log4j.LogManager;
@@ -241,7 +242,23 @@ static org.apache.logging.log4j.Level getLog4jLevel(Level level) {
   }
 
   private static org.apache.logging.log4j.Marker m(Marker m) {
-    return (m == null) ? null : ((org.apache.logging.slf4j.Log4jMarker) m).getLog4jMarker();
+    if (m == null) {
+      return null;
+    }
+
+    Field markerField = null;
+    try {
+      markerField = m.getClass().getDeclaredField("marker");
+      markerField.setAccessible(true);
+      return (org.apache.logging.log4j.Marker) markerField.get(m);
+    } catch (Exception e) {
+      // Well, best effort...
+      return null;
+    } finally {
+      if (markerField != null) {
+        markerField.setAccessible(false);
+      }
+    }
   }
 
   /*

From fafdb225d5c829b0841805c0f97cab676084d9d1 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 7 Dec 2022 13:34:17 +0100
Subject: [PATCH 92/94] #270 - Update dependencies

- log4j 2.17.1 -> 2.19.0
- junit 5.8.2 -> 5.9.1
- assertj 3.22.0 -> 3.23.1
---
 uimaj-parent/pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml
index 973d251a7e..403bc1f85b 100644
--- a/uimaj-parent/pom.xml
+++ b/uimaj-parent/pom.xml
@@ -142,10 +142,10 @@
      properties already, they should be injected manually into the plugins. 
     -->
     1.7.36
-    2.17.1
+    2.19.0
     2.13.1
-    5.8.2
-    3.22.0
+    5.9.1
+    3.23.1
     2.9.0
     3.2.5
 

From f00a360804f71204f59edd495c7f28d531da8336 Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 11 Jan 2023 07:39:07 +0100
Subject: [PATCH 93/94] #270 - Update dependencies

- p2-layout-resolver 1.3.0 -> 1.5.0
---
 uimaj-parent/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/uimaj-parent/pom.xml b/uimaj-parent/pom.xml
index 403bc1f85b..7d8982ee82 100644
--- a/uimaj-parent/pom.xml
+++ b/uimaj-parent/pom.xml
@@ -305,7 +305,7 @@
       
         org.openntf.maven
         p2-layout-resolver
-        1.3.0
+        1.5.0
         true
       
 

From c1c89117bb260da50f254882ae580bd8fee2657d Mon Sep 17 00:00:00 2001
From: Richard Eckart de Castilho 
Date: Wed, 11 Jan 2023 07:40:46 +0100
Subject: [PATCH 94/94] No issue: Remove Jira line from PR template - we do not
 use Jira anymore.

---
 .github/PULL_REQUEST_TEMPLATE.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index b2e525db29..f436f61bdb 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,5 +1,3 @@
-**JIRA Ticket:** https://issues.apache.org/jira/browse/UIMA-XXXX
-
 **What's in the PR**
 * ...