diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 68299d5..648aa49 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -14,9 +14,9 @@ body: attributes: label: "Checklist" options: - - label: "I am able to reproduce the bug with the [latest version](https://github.com/xdev-software/template-placeholder/releases/latest)" + - label: "I am able to reproduce the bug with the [latest version](https://github.com/xdev-software/micro-migration/releases/latest)" required: true - - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/template-placeholder/issues) or [closed](https://github.com/xdev-software/template-placeholder/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/micro-migration/issues) or [closed](https://github.com/xdev-software/micro-migration/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." required: true - label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise." required: true diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 7523129..40eac88 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -12,7 +12,7 @@ body: attributes: label: "Checklist" options: - - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/template-placeholder/issues) or [closed](https://github.com/xdev-software/template-placeholder/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/micro-migration/issues) or [closed](https://github.com/xdev-software/micro-migration/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." required: true - label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise." required: true diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index 6ecd6ad..a766c85 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -12,7 +12,7 @@ body: attributes: label: "Checklist" options: - - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/template-placeholder/issues) or [closed](https://github.com/xdev-software/template-placeholder/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/micro-migration/issues) or [closed](https://github.com/xdev-software/micro-migration/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." required: true - label: "I have taken the time to fill in all the required details. I understand that the question will be dismissed otherwise." required: true diff --git a/.run/Run Demo.run.xml b/.run/Run Demo.run.xml deleted file mode 100644 index 5fb2bc2..0000000 --- a/.run/Run Demo.run.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29..33d04bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,37 @@ +## 2.0.0 +_Major refactoring_ +* Consolidated all previous modules into a single one +* Dropped support for MicroStream as EclipseStore is it's successor +* Refactored and adjusted code accordingly +* Slimed down dependencies +* Minimal required Java version: 17 + +## 1.0.0 +* Added support for EclipseStore v1 +* Updated plenty of libraries + +## 0.0.9 +* Added support for MicroStream v8 + +## 0.0.8 +* Access to the native embedded manager is now possible in the scripts (see ``VersionAgnosticMigrationEmbeddedStorageManager#getNativeStorageManager``) + +## 0.0.7 +* A lot of refactoring of the module structure +* A migration history is now available and automatically stored + +## 0.0.6 +* Tried a new release-action...again. + +## 0.0.5 +* Tried a new release-action. + +## 0.0.4 +* Fixed setup. 0.0.3 was not working with the release setup. + +## 0.0.3 +* Restructured the complete maven modules. Multiple MicroStream-Versions are now supported. +* Added plenty of documentation + +## 0.0.2 +* Updated MicroStream from v4 to v5. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be2a186..0a8c07c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,10 +34,10 @@ You should have the following things installed: * Ensure that the JDK/Java-Version is correct -## Releasing [![Build](https://img.shields.io/github/actions/workflow/status/xdev-software/template-placeholder/release.yml?branch=master)](https://github.com/xdev-software/template-placeholder/actions/workflows/release.yml) +## Releasing [![Build](https://img.shields.io/github/actions/workflow/status/xdev-software/micro-migration/release.yml?branch=master)](https://github.com/xdev-software/micro-migration/actions/workflows/release.yml) Before releasing: -* Consider doing a [test-deployment](https://github.com/xdev-software/template-placeholder/actions/workflows/test-deploy.yml?query=branch%3Adevelop) before actually releasing. +* Consider doing a [test-deployment](https://github.com/xdev-software/micro-migration/actions/workflows/test-deploy.yml?query=branch%3Adevelop) before actually releasing. * Check the [changelog](CHANGELOG.md) If the ``develop`` is ready for release, create a pull request to the ``master``-Branch and merge the changes diff --git a/README.md b/README.md index eccf80b..005e798 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,120 @@ -[![Latest version](https://img.shields.io/maven-central/v/software.xdev/template-placeholder?logo=apache%20maven)](https://mvnrepository.com/artifact/software.xdev/template-placeholder) -[![Build](https://img.shields.io/github/actions/workflow/status/xdev-software/template-placeholder/check-build.yml?branch=develop)](https://github.com/xdev-software/template-placeholder/actions/workflows/check-build.yml?query=branch%3Adevelop) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=xdev-software_template-placeholder&metric=alert_status)](https://sonarcloud.io/dashboard?id=xdev-software_template-placeholder) +[![Latest version](https://img.shields.io/maven-central/v/software.xdev/micro-migration?logo=apache%20maven)](https://mvnrepository.com/artifact/software.xdev/micro-migration) +[![Build](https://img.shields.io/github/actions/workflow/status/xdev-software/micro-migration/check-build.yml?branch=develop)](https://github.com/xdev-software/micro-migration/actions/workflows/check-build.yml?query=branch%3Adevelop) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=xdev-software_micro-migration&metric=alert_status)](https://sonarcloud.io/dashboard?id=xdev-software_micro-migration) -# template-placeholder +# XDEV MicroMigration Logo +Tiny java library to migrate [EclipseStore](https://github.com/eclipse-store/store) datastores. +Applies migration scripts on the datastores to keep them up to date. +## Intro +When you think about default database setup, you probably imagine something like this: + +![Imaginative system layout](./assets/MigrationSequence_1.png "Imaginative system layout") + +Yet in reality most workflows involve different systems like test systems and production systems. +In code this workflow is represented with version-control systems and different branches. + +![Code workflow](./assets/MigrationSequence_2.png "Code workflow") + +For this code workflow to behave correctly, for each system a separate datastore is needed. +To keep these datastores to represent the correspondend data for the code is a hassle. + +![Code workflow with datastore](./assets/MigrationSequence_3.png "Code workflow with datastore") + +That's why migration frameworks like [Flyway](https://flywaydb.org) and [Liquibase](https://www.liquibase.org/) exist. +Unfortunately both these frameworks are designed to support any type of SQL databases but no NoSQL databases like [EclipseStore](https://eclipsestore.io/). This led to the creation of this library. + +This library delivers an easy concept to keep your EclipseStore datastore versioned with migration scripts written in plain java. +It's easy to create code, that automatically brings a datastore with an older version to the version, suited to the current code. + +![Migrate datastore to new version](./assets/MigrationSequence_4.png "Migrate datastore to new version") + +## Approaches +There are two possible usages with the Micro migration library: + +The **first**, easier approach is to use the `MigrationEmbeddedStorageManager`. +It can be used on a brand new datastore or introduced later, after a EclipseStore datastore is already in use. +Only the storage manager (`MigrationEmbeddedStorageManager`) knows about the versioning. +The rest of application does not know about the version and can have no regards about it. + +### MigrationEmbeddedStorageManager +Extensive examples can be found in its own [own module](./micro-migration-demo). +A simple example where scripts need to be registered in the `ExplicitMigrater`: + +```java +public static void main(String[] args){ + ExplicitMigrater migrater = new ExplicitMigrater(new UpdateToV1_0()); + MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(migrater); + // Do some business logic + storageManager.shutdown(); +} +``` + +The update scripts can look like this: + +```java +public class UpdateToV1_0 implements MigrationScript +{ + @Override + public MigrationVersion getTargetVersion(){ + return new MigrationVersion(1); + } + + @Override + public void migrate(Context context){ + // Logic of the update + context.getStorageManager().setRoot("Update 1.0"); + } +} +``` + +### MigrationManager +Although the approach with the `MigrationEmbeddedStorageManager` is pretty easy to handle, it is intrusive in the way, that it replaces the root entry point of the EclipseStore datastore and inserts its own `VersionedRoot` as root. Some users might find this too entrusive. + +That's why a second approach can be used, where the `MigrationManager` is used. This class is also used internally by the `MigrationEmbeddedStorageManager`. + +```java +public static void main(String[] args){ + ExplicitMigrater migrater = new ExplicitMigrater(new UpdateToV1_0()); + EmbeddedStorageManager storageManager = EmbeddedStorage.start(); + VersionedObject versionedRoot =(VersionedObject)storageManager.root(); + new MigrationManager(versionedRoot, migrater, storageManager).migrate(versionedBranch); + // Do some business logic + storageManager.shutdown(); +} +``` + +## Migrater +### ExplicitMigrater +Scripts for the migrations must be registered in a `MicroMigrater`. +The simplest way for this is to use the `ExplicitMigrater` and just put the scripts in the constructor. +A downside of this method is that you need to register all scripts (new or old) manually in the constructor. + +```java +final ExplicitMigrater migrater = new ExplicitMigrater( + new UpdateToV1_0(), + new UpdateToV1_1() +); +``` + +### ReflectiveMigrater +For a more convenient usage the `ReflectiveMigrater` was built. +You simply instanciate a object of this class with the package name of your `MicroMigrationScript`s. +The `ReflectiveMigrater` will search for any implementations of `MicroMigrationScript` in the given package. +This way scripts can simply be placed in the same package and on startup of the application all scripts are loaded in. + +```java +final ReflectiveMigrater migrater = new ReflectiveMigrater("software.xdev.micromigration.examples.reflective.scripts"); +``` ## Installation -[Installation guide for the latest release](https://github.com/xdev-software/template-placeholder/releases/latest#Installation) +[Installation guide for the latest release](https://github.com/xdev-software/micro-migration/releases/latest#Installation) + +### Compatibility +| Eclipse Store version | micro-migration version | +| --- | --- | +| [EclipseStore](https://github.com/eclipse-store/store) 1+ | ``2+`` | +| [MicroStream](https://github.com/microstream-one/microstream) 5-8
EclipseStore 1.1 | ``1.x`` | ## Support If you need support as soon as possible and you can't wait for any pull request, feel free to use [our support](https://xdev.software/en/services/support). @@ -15,4 +123,4 @@ If you need support as soon as possible and you can't wait for any pull request, See the [contributing guide](./CONTRIBUTING.md) for detailed instructions on how to get started with our project. ## Dependencies and Licenses -View the [license of the current project](LICENSE) or the [summary including all dependencies](https://xdev-software.github.io/template-placeholder/dependencies) +View the [license of the current project](LICENSE) or the [summary including all dependencies](https://xdev-software.github.io/micro-migration/dependencies) diff --git a/SECURITY.md b/SECURITY.md index 34b9514..ad1a2fc 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,4 +2,4 @@ ## Reporting a Vulnerability -Please report a security vulnerability [on GitHub Security Advisories](https://github.com/xdev-software/template-placeholder/security/advisories/new). +Please report a security vulnerability [on GitHub Security Advisories](https://github.com/xdev-software/micro-migration/security/advisories/new). diff --git a/assets/Logo.png b/assets/Logo.png new file mode 100644 index 0000000..199eebd Binary files /dev/null and b/assets/Logo.png differ diff --git a/assets/Logo2.png b/assets/Logo2.png new file mode 100644 index 0000000..b154b33 Binary files /dev/null and b/assets/Logo2.png differ diff --git a/assets/MigrationSequence.drawio b/assets/MigrationSequence.drawio new file mode 100644 index 0000000..4d51a09 --- /dev/null +++ b/assets/MigrationSequence.drawio @@ -0,0 +1 @@ +7V1bd6I6FP41fTxdgXDz0VtbusR2qp2OviGkiKK4ABX89ScoVK6KjiKek1ljhRBCsvPtvb+EZPsAmzP32ZIXY8lUkfFAA9V9gK0HmqZYFuAvP8XbpQgc3CVolq4GmfYJPX2DgsTgPm2pq8iOZXRM03D0RTxRMedzpDixNNmyzHU827dpxJ+6kDWUSugpspFO/dJVZxykUlxtf+EF6do4eLRA87sLMznMHLTEHsuquY4kwfYDbFqm6eyOZm4TGb7wQrns7nvKufpTMQvNnSI3iCtlyk1setUE7qepeI7Ze/mHEnbFrGRjGbQ4qK3jhSLAFV/4h98Gcuu+SB9gA83V4LClGLJt6wpOHDszAydQ+PDbnDtP8kw3/G7vIc1EuMxPcXunY3l/cCoITwb+ySMbnrbc6MWWF565uvMnKN0/jtyFz/Y3+SfhPd+6YTRNw7S2DYHN7T+cvmsiUlNdv5dlkGSbS0tBBwQYoNmRLQ05B/LVfnocqwoyZwi3Dd+33mMq1JRxBE1hmoUM2dFX8erKAbS1n+J+nvBu6rghNAjVkGN3t4RKGJYbFrFrZnBXFEOJgrBCxwsCiYJ2ckgVhA8izd4nbSF6ClxrBK5/BddaQbhS9C3xSkMQgxnLn4lXCNjDBV0Zr6HtJ3g9E68UXRSw7E0ByyQAK5wL2ISBTRV0bcBSxwGrWeZyEWRDloPcmNACIiaPwuwgp/fTfRUWRMWFyYRKG+lLis7oTDrpjaIdF5PUqWKBGVLhDPzYhqqv8KHmH3ZMTBtxLklWxvochTnwAyOZUtLEwpyrSA1Ubz3WHdRbyFulWGNKHdd7X946fkrd0LU5TnPMRVoPv2WVl32DYTuWOUWRKyOGYwFz0H74V3pB7ajcTo525gEcHVTHkrswDeyW7Mi2Y1oo1yTrs+3o4EfsHXmEjHfT1h3d9MU/Mh3HnOX2y/b2ur3YjUt8iymHJ9+66/d5I3hCS8V1eYD13Sn9ZK+0B7rh4n6nm+8vXXroNZjRl7tUNkCXXz6A0jJXHahC1WOh5LErZaaspEl9LTVrG3Wm6OLL0FDm3cWIZmripO2fL4Z/1OYIavi8rknNOnjbfkRt+MWOBzPX6Hy9jge0M1dmNWo0+1UTZ6yhevW12Kpr3Zbmf/R3fTBBz21ebNY1seXOxefhYvS8rol6ty19SuCjP43n2X0E5fkJyM3G9L332pU2mt0Fmiu1JaYzmdpdb810Wsryred/G3R3Jq07rfZS6q3X/nVJX3ud1qspTcYTqce4nVYdp4HgGvB+T4xWF6d1PYbttCS2M2n7ZW7emmuIdHFVpD5S3xClfmPS6QfP7Yu21MTl+d/zAT3Y4Gfunu3XE9cHp8807+1Zcv3nSU2c1g+u9V/pTn+4rZPUn/ppm7ftvW2/foz/Xbhem6fr1GvTjtRLcnf1ktxUvVrr1XDDzEQ4Hr9t1isFDufvmq8k/v8DZuTyliN0kFzMN8C0a2CEtFkJ0y5uVeiUVWmaKjEo5xqU9Yh22SFdW+4Ni8RK7W7jYzLFz2ys5C8W+HXeKnzrU8NKDrq9ug9eTfKVwasDDHpX8pJAziq7+yR9DqiP6WesbKx4y25v7Xabde9t/w06k0+9EyqDt1NYLMeZ/OXa7z1xgpUddqe/PHESy7P9vL+8GgP4S0MtXH5/gJ83xXITXVFvQPnrA8jbdCzn57Ehf6mm6p/nGYnZ74nabDD4mW5XFzXUx3knfhvUxfDlw/TTcfs1+fn3YkiPAT73RB1rQONV7zKDvv1TKywVb/jVBeKL34ttGteG9XO/9URNpY2p+rxNhzjdHH4Zc/nll1/rpBQOtFDaxFsoHW5h1c3ND2e5mb1JG5zS+TkEQtX4eXpaqCnigpqtcuh2TWWz6LaMGArSpdDt49M1ZdPt9MwH4duEbxO+XTm+nWM6qsm3qfQwnhBuQrgJ4b4fwn2Svbk94c6a+i2ZcLOArxrhDt/LRMTSR7ZTAt0eAQQRl0W3ARKAIJRCt2Hl6HYapoRuE7pN6Hbl6HaO6ago3WYI3SZ0m9DtO6bbJ9mb29PttMEpnW7ziUVjVaDbbIZYUgtQ3i1TXSpbU3urtScjSlW/QRY7pwAPa6gUds5Ujp1zhJ0Tdk7YefXZeY7pqCg75wk7J+ycsPM7Zucn2Zvbs/MsGloyO0+uDhduTs7pNLvrebaDZiXw7Uqs9T6+9aLsHkk7RsK3Cd8mfLtyfDvHdFSTb9PpzdKEbxO+Tfj2/fDtk+zN7fk22e6e3bmFozMUDc8A+aMctsT4DBydYMbnxmcoe7976KEJYM8FLF8QsMzxDbYlBmiAzJmATQZoSBV0bcAW2O9OAHsUh0UAW6kADfDcCDjJAA2pgq4N2P9rKALYUPC5jFtjBeguRANPm0yEGYwvc+6KSnroy4WaSM+xkkEmGWSSQWbJg8xrWBsmMZ/F3Xh8CTNeIN/jvtmr9FZym3MVfEPGPmfiG4hvIL7h7n0DZJhq+QYmPTK+vx1eV+mq5Ha8CjgGJj0qJI6BOAbiGO7fMbChblfGMfwP9yJcpWeT+0yq4EfIimLiR4gf+S/6ET4k9JXxIwUWN5S9mJgvvNUv+Z7yYmIJ3yfd+Wri4Hz3ey4U81erdpjjP55RdicdjCbNYYG5ddzk38iytwwI7EkQoB9BJAtxrWQ5MlmOfNHlyBfa1pBndXLWJtdu601ZOoe5ZxgjYoEIuSfk/g6XL59mkijmxgyfqwDD52DlGD5PGH42UqrE8PlTGT5xqoTWE1pffVqfZ2qqSet5QusJrSe0/r9N608zSTen9XwFQmLTfILWZ+wNp1k2LZXUBqPLzcAUei/ec2TL8UUD1AidvPgL8nyYypYScHa28JulAzDIf7UC6FgPsQXHXfBq/ZMO05LRP6KNsywXuHNQZNp+ZO27JbuzUgXJK1k3tgj3f3Xe+rvCVoGTh09FwTI2Z6Ol/TdAuSIy2Mf4ygcqCxxhSPMoOJK/hns5cKQXPnwgWY2rKQi74c5VswaS8gcZ8mcy5H895UyH1mi7SFlutfBHHW3F0heOfbfyD8RNZy30KVXcXIFtr7gYfWGjuPDCQQSaq9iTOSg9wwS2/7JmmH6u3MLmsIm1VlS6C2CZ3ohLD+wO9EAxGc/N+eFFbdcTb7hw7GbiLMBJj+7ZztktfUyeB/dRH2TQR3dXhyg5uruavenu6uSm6NQCxcK7qxOBMEoOX8EViD5+hygKbd9xFN04CorwCHlICzxkeMgJXHzc+w94BILAcDxk8TcQqFr46xSnoozi4CNPMbTABn8Tv2daMugKBNW8R9AVjWSyG5fdDHT8QdDVHmsUxUKaY/B3jUpMqRQGHH8QcCWHkOCyBsJXB1wYvyQMUlIkfokPz3DKHxkjc93eJ5SA4NsCUzgITOoyyAzfLyRHJkegiLEhe5FsCz+Dnd+YnMfsgb0r8LIwTw/pS4T5KWF6ojA3LWdsauZcNqJY3wcN2scJGjxEwwTlBA3ylQYfh69yylObAoafu2kIq4xZqNqZrJWvPUKGw8oo7P7GF9oX5ROn6hTNZlc/NzZcIn84mZbvtMCh/FdS2vQ8UBlKe1wBQ+/1o8qDiJLnqPWZSnt9DRXuQ0OppIamIoYX1VDhsIaWTMD4AsPMs4LOleKtrg9PcEvU0XGrR50bKI5NlMOVjLECo8qSMHZmwMMCOCsae5C/KaLYROxB4VyeAYUjBZ2NKXxqmaYTzW7Ji7FkqsjP8S8= \ No newline at end of file diff --git a/assets/MigrationSequence_1.png b/assets/MigrationSequence_1.png new file mode 100644 index 0000000..4b8c8da Binary files /dev/null and b/assets/MigrationSequence_1.png differ diff --git a/assets/MigrationSequence_2.png b/assets/MigrationSequence_2.png new file mode 100644 index 0000000..3df6247 Binary files /dev/null and b/assets/MigrationSequence_2.png differ diff --git a/assets/MigrationSequence_3.png b/assets/MigrationSequence_3.png new file mode 100644 index 0000000..96f67d2 Binary files /dev/null and b/assets/MigrationSequence_3.png differ diff --git a/assets/MigrationSequence_4.png b/assets/MigrationSequence_4.png new file mode 100644 index 0000000..674f696 Binary files /dev/null and b/assets/MigrationSequence_4.png differ diff --git a/micro-migration-demo/README.md b/micro-migration-demo/README.md new file mode 100644 index 0000000..a167b03 --- /dev/null +++ b/micro-migration-demo/README.md @@ -0,0 +1,21 @@ +# micro-migration-examples +Examples for the MicroMigration-Library + +Currently contains four major examples: +## Example with `ExplicitMigrater` +In the package `software.xdev.micromigration.examples.explicit` there is a simple example with explicitly listed upgrade scripts. +This is the most straight forward approach to use migration scripts. + +## Example with `ReflectiveMigrater` +In package `software.xdev.micromigration.examples.reflective` a migrater which finds it's scripts through reflection is used. +So here all `MicroMigrationScript`s in the defined `software.xdev.micromigration.examples.reflective.scripts` package are used. + +## Practical examples +The package `software.xdev.micromigration.examples.practical.embedded` contains examples +that are just a bit more complex than the other examples and should allow an insight about the usage in a +practical environment. + +There is one example implemented with the `MigrationEmbeddedStorageManager` and another with the +plain `MigrationManager`, so it is clear what the difference between these two approaches is. +In both implementations the first update migrates from version 0 to 1 and converts an "old" `BusinessBranch` +to a newer one. The second update only adds more `Customer`s to the existing `BusinessBranch`. diff --git a/template-placeholder-demo/pom.xml b/micro-migration-demo/pom.xml similarity index 54% rename from template-placeholder-demo/pom.xml rename to micro-migration-demo/pom.xml index 1af633c..a9f75d2 100644 --- a/template-placeholder-demo/pom.xml +++ b/micro-migration-demo/pom.xml @@ -6,12 +6,12 @@ software.xdev - template-placeholder-root - 1.0.0-SNAPSHOT + micro-migration-root + 2.0.1-SNAPSHOT - template-placeholder-demo - 1.0.0-SNAPSHOT + micro-migration-demo + 2.0.1-SNAPSHOT jar @@ -25,16 +25,20 @@ UTF-8 UTF-8 - - software.xdev.Application software.xdev - template-placeholder + micro-migration ${project.version} + + + org.slf4j + slf4j-simple + 2.0.13 + @@ -52,34 +56,6 @@ - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - - ${mainClass} - - - true - - - - jar-with-dependencies - - false - - - - make-assembly - package - - single - - - - diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/MainExplicit.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/MainExplicit.java new file mode 100644 index 0000000..e2f93c3 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/MainExplicit.java @@ -0,0 +1,58 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.explicit; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.examples.explicit.scripts.UpdateToV1_0; +import software.xdev.micromigration.examples.explicit.scripts.UpdateToV1_1; +import software.xdev.micromigration.migrater.ExplicitMigrater; + + +/** + * The most basic usage of micro migration. Here two {@link MigrationScript}s are explicitly registered and subsequently + * executed. Easy. + */ +@SuppressWarnings("java:S2629") +public final class MainExplicit +{ + private static final Logger LOG = LoggerFactory.getLogger(MainExplicit.class); + + public static void main(final String[] args) + { + final ExplicitMigrater migrater = new ExplicitMigrater( + new UpdateToV1_0(), + new UpdateToV1_1() + ); + final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(migrater); + LOG.info(storageManager.root().toString()); + if(storageManager.root() == null) + { + storageManager.setRoot("Hello World! @ " + new Date()); + } + storageManager.storeRoot(); + storageManager.shutdown(); + } + + private MainExplicit() + { + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/scripts/UpdateToV1_0.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/scripts/UpdateToV1_0.java new file mode 100644 index 0000000..0cafd7a --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/scripts/UpdateToV1_0.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.explicit.scripts; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV1_0 implements MigrationScript +{ + private static final Logger LOG = LoggerFactory.getLogger(UpdateToV1_0.class); + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 0); + } + + @Override + public void migrate(final Context context) + { + LOG.info("Update {} executed", this.getTargetVersion()); + context.getStorageManager().setRoot("Hello World! @ " + new Date() + " Update 1.0"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/scripts/UpdateToV1_1.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/scripts/UpdateToV1_1.java new file mode 100644 index 0000000..14c5869 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/explicit/scripts/UpdateToV1_1.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.explicit.scripts; + +import java.util.Date; + +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV1_1 implements MigrationScript +{ + private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(UpdateToV1_1.class); + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 1); + } + + @Override + public void migrate(final Context context) + { + LOG.info("Update {} executed", this.getTargetVersion()); + context.getStorageManager().setRoot("Hello World! @ " + new Date() + " Update 1.1"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/notification/MainNotification.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/notification/MainNotification.java new file mode 100644 index 0000000..92526b2 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/notification/MainNotification.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.notification; + +import java.util.Date; +import java.util.logging.Logger; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +/** + * Shows the basic registration of migration notifications ({@link ScriptExecutionNotification}). + */ +@SuppressWarnings("java:S2629") +public final class MainNotification +{ + public static void main(final String[] args) + { + final ExplicitMigrater migrater = new ExplicitMigrater( + new MainNotification.UpdateToV1_0() + ); + migrater.registerNotificationConsumer( + scriptExecutionNotification -> Logger.getGlobal() + .info("Script " + scriptExecutionNotification.getExecutedScript().getClass().getSimpleName() + + " executed.") + ); + final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(migrater); + Logger.getGlobal().info(storageManager.root().toString()); + if(storageManager.root() == null) + { + storageManager.setRoot("Hello World! @ " + new Date()); + } + storageManager.storeRoot(); + storageManager.shutdown(); + } + + @SuppressWarnings({"checkstyle:TypeName", "java:S101"}) + static class UpdateToV1_0 implements VersionAgnosticMigrationScript + { + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 0); + } + + @Override + public void migrate(final Context context) + { + context.getStorageManager().setRoot("Hello World! @ " + new Date() + " Update 1.0"); + } + } + + private MainNotification() + { + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/MainPracticalWithMigrationEmbeddedStorageManager.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/MainPracticalWithMigrationEmbeddedStorageManager.java new file mode 100644 index 0000000..a1af149 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/MainPracticalWithMigrationEmbeddedStorageManager.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.embedded; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.examples.practical.v0.BusinessBranch; +import software.xdev.micromigration.migrater.ExplicitMigrater; + + +/** + * A practical example of usage in a few steps: + *
    + *
  • v0.0: Storage is created without any updates. Only stores a new {@link BusinessBranch} + *
  • v1.0: The BusinessBranch has a new implementation {@link BusinessBranch}. + * The old branch is converted to the new implementation through the {@link UpdateToV1_0} script. + *
  • v2.0: A new customer is added through the {@link UpdateToV2_0} script. + *
+ * The storage is restarted after every update to simulate a complete lifecycle of the datastore. + */ +@SuppressWarnings("java:S2629") +public final class MainPracticalWithMigrationEmbeddedStorageManager +{ + private static final Logger LOG = LoggerFactory.getLogger(MainPracticalWithMigrationEmbeddedStorageManager.class); + + public static void main(final String[] args) + { + // V0.0 + final ExplicitMigrater emptyMigrater = new ExplicitMigrater(); + try(final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(emptyMigrater)) + { + storageManager.setRoot(BusinessBranch.createDummyBranch()); + storageManager.storeRoot(); + LOG.info(storageManager.root().toString()); + } + + // V1.0 + final ExplicitMigrater migraterWithV1 = new ExplicitMigrater(new UpdateToV1_0()); + try(final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(migraterWithV1)) + { + LOG.info(storageManager.root().toString()); + } + + // V2.0 + final ExplicitMigrater migraterWithV2 = new ExplicitMigrater( + new UpdateToV1_0(), + new UpdateToV2_0() + ); + try(final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(migraterWithV2)) + { + LOG.info(storageManager.root().toString()); + } + } + + private MainPracticalWithMigrationEmbeddedStorageManager() + { + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/UpdateToV1_0.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/UpdateToV1_0.java new file mode 100644 index 0000000..b2cf6e1 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/UpdateToV1_0.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.embedded; + +import java.util.logging.Logger; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.examples.practical.v1_and_higher.Address; +import software.xdev.micromigration.examples.practical.v1_and_higher.BusinessBranch; +import software.xdev.micromigration.examples.practical.v1_and_higher.Customer; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV1_0 implements MigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 0); + } + + @Override + public void migrate( + final Context context) + { + Logger.getGlobal().info("Executing Script for v1.0..."); + final software.xdev.micromigration.examples.practical.v0.BusinessBranch oldBranch = + context.getMigratingObject(); + final BusinessBranch newBranch = + new BusinessBranch(); + for(final software.xdev.micromigration.examples.practical.v0.Customer oldCustomer : oldBranch.customers) + { + final Customer newCustomer = + new Customer(); + newCustomer.name = oldCustomer.name; + newCustomer.address = new Address(); + newCustomer.address.number = oldCustomer.number; + newCustomer.address.street = oldCustomer.street; + newCustomer.address.city = oldCustomer.city; + newBranch.customers.add(newCustomer); + } + context.getStorageManager().setRoot(newBranch); + context.getStorageManager().storeRoot(); + Logger.getGlobal().info("Done executing Script for v1.0"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/UpdateToV2_0.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/UpdateToV2_0.java new file mode 100644 index 0000000..8e90bf0 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/embedded/UpdateToV2_0.java @@ -0,0 +1,51 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.embedded; + +import java.util.logging.Logger; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.examples.practical.v1_and_higher.BusinessBranch; +import software.xdev.micromigration.examples.practical.v1_and_higher.Customer; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV2_0 implements MigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(2, 0); + } + + @Override + public void migrate(final Context context) + { + Logger.getGlobal().info("Executing Script for v2.0..."); + final BusinessBranch branch = context.getMigratingObject(); + final Customer newCustomer = new Customer(); + newCustomer.name = "Stevie Nicks"; + newCustomer.address.number = 5; + newCustomer.address.street = "Fleetwood Street"; + newCustomer.address.city = "Phoenix"; + branch.customers.add(newCustomer); + context.getStorageManager().store(branch.customers); + Logger.getGlobal().info("Done executing Script for v2.0"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/MainPracticalWithMigrationManager.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/MainPracticalWithMigrationManager.java new file mode 100644 index 0000000..5f5c16e --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/MainPracticalWithMigrationManager.java @@ -0,0 +1,87 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.migration_manager; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationManager; +import software.xdev.micromigration.examples.practical.v0.BusinessBranch; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.version.VersionedObject; + + +/** + * A practical example of usage in a few steps: + *
    + *
  • v0.0: Storage is created without any updates. Only stores a new {@link BusinessBranch} + *
  • v1.0: The BusinessBranch has a new implementation + * {@link software.xdev.micromigration.examples.practical.v1_and_higher.BusinessBranch}. + * The old branch is converted to the new implementation through the {@link UpdateToV1_0} script. + *
  • v2.0: A new customer is added through the {@link UpdateToV2_0} script. + *
+ * The storage is restarted after every update to simulate a complete lifecycle of the datastore. + */ +@SuppressWarnings("java:S2629") +public final class MainPracticalWithMigrationManager +{ + private static final Logger LOG = LoggerFactory.getLogger(MainPracticalWithMigrationManager.class); + + /** + * Suppressed Warning "unchecked" because it is given, that the correct object is returned. + */ + @SuppressWarnings("unchecked") + public static void main(final String[] args) + { + // V0.0 + try(final EmbeddedStorageManager storageManager = EmbeddedStorage.start()) + { + final VersionedObject versionedBranch = + new VersionedObject<>(BusinessBranch.createDummyBranch()); + storageManager.setRoot(versionedBranch); + storageManager.storeRoot(); + LOG.info(storageManager.root().toString()); + } + + // V1.0 + try(final EmbeddedStorageManager storageManager = EmbeddedStorage.start()) + { + final ExplicitMigrater migraterWithV1 = new ExplicitMigrater(new UpdateToV1_0()); + final VersionedObject versionedBranch = + (VersionedObject)storageManager.root(); + new MigrationManager(versionedBranch, migraterWithV1, storageManager) + .migrate(versionedBranch); + LOG.info(storageManager.root().toString()); + } + + // V2.0 + try(final EmbeddedStorageManager storageManager = EmbeddedStorage.start()) + { + final ExplicitMigrater migraterWithV2 = new ExplicitMigrater(new UpdateToV1_0(), new UpdateToV2_0()); + final VersionedObject versionedBranch = + (VersionedObject)storageManager.root(); + new MigrationManager(versionedBranch, migraterWithV2, storageManager) + .migrate(versionedBranch); + LOG.info(storageManager.root().toString()); + } + } + + private MainPracticalWithMigrationManager() + { + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/UpdateToV1_0.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/UpdateToV1_0.java new file mode 100644 index 0000000..41b0e45 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/UpdateToV1_0.java @@ -0,0 +1,66 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.migration_manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.examples.practical.v0.BusinessBranch; +import software.xdev.micromigration.examples.practical.v0.Customer; +import software.xdev.micromigration.examples.practical.v1_and_higher.Address; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.version.VersionedObject; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV1_0 implements MigrationScript> +{ + private static final Logger LOG = LoggerFactory.getLogger(UpdateToV1_0.class); + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 0); + } + + @Override + public void migrate(final Context, MigrationEmbeddedStorageManager> context) + { + LOG.info("Executing Script for v1.0..."); + final VersionedObject versionedBranch = context.getMigratingObject(); + final BusinessBranch oldBranch = + (BusinessBranch)versionedBranch.getObject(); + final software.xdev.micromigration.examples.practical.v1_and_higher.BusinessBranch newBranch = + new software.xdev.micromigration.examples.practical.v1_and_higher.BusinessBranch(); + for(final Customer oldCustomer : oldBranch.customers) + { + final software.xdev.micromigration.examples.practical.v1_and_higher.Customer newCustomer = + new software.xdev.micromigration.examples.practical.v1_and_higher.Customer(); + newCustomer.name = oldCustomer.name; + newCustomer.address = new Address(); + newCustomer.address.number = oldCustomer.number; + newCustomer.address.street = oldCustomer.street; + newCustomer.address.city = oldCustomer.city; + newBranch.customers.add(newCustomer); + } + versionedBranch.setObject(newBranch); + context.getStorageManager().store(versionedBranch); + LOG.info("Done executing Script for v1.0"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/UpdateToV2_0.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/UpdateToV2_0.java new file mode 100644 index 0000000..dc24082 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/migration_manager/UpdateToV2_0.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.migration_manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.examples.practical.v1_and_higher.BusinessBranch; +import software.xdev.micromigration.examples.practical.v1_and_higher.Customer; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.version.VersionedObject; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV2_0 implements MigrationScript> +{ + private static final Logger LOG = LoggerFactory.getLogger(UpdateToV2_0.class); + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(2, 0); + } + + @Override + public void migrate(final Context, MigrationEmbeddedStorageManager> context) + { + LOG.info("Executing Script for v2.0..."); + final VersionedObject versionedBranch = context.getMigratingObject(); + final BusinessBranch branch = versionedBranch.getObject(); + final Customer newCustomer = new Customer(); + newCustomer.name = "Stevie Nicks"; + newCustomer.address.number = 5; + newCustomer.address.street = "Fleetwood Street"; + newCustomer.address.city = "Phoenix"; + branch.customers.add(newCustomer); + context.getStorageManager().store(branch.customers); + LOG.info("Done executing Script for v2.0"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v0/BusinessBranch.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v0/BusinessBranch.java new file mode 100644 index 0000000..6f79269 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v0/BusinessBranch.java @@ -0,0 +1,55 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.v0; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + + +@SuppressWarnings("checkstyle:VisibilityModifier") +public class BusinessBranch +{ + public final List customers = new ArrayList<>(); + + @Override + public String toString() + { + return "Branch v0\n" + + "Customers:\n" + + this.customers.stream() + .map(c -> c.name) + .collect(Collectors.joining("\n")); + } + + public static BusinessBranch createDummyBranch() + { + final BusinessBranch branch = new BusinessBranch(); + final Customer customer1 = new Customer(); + customer1.name = "Mick Fleetwood"; + customer1.number = 1; + customer1.street = "Fleetwood Street"; + customer1.city = "Redruth"; + branch.customers.add(customer1); + final Customer customer2 = new Customer(); + customer2.name = "Lindsey Buckingham"; + customer2.number = 2; + customer2.street = "Mac Street"; + customer2.city = "Palo Alto"; + branch.customers.add(customer2); + return branch; + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v0/Customer.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v0/Customer.java new file mode 100644 index 0000000..e26f77a --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v0/Customer.java @@ -0,0 +1,27 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.v0; + +@SuppressWarnings({"checkstyle:VisibilityModifier", "java:S1104"}) +public class Customer +{ + public String name; + + // Oversimplified old address format + public int number; + public String street; + public String city; +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/Address.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/Address.java new file mode 100644 index 0000000..8bb434a --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/Address.java @@ -0,0 +1,24 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.v1_and_higher; + +@SuppressWarnings({"checkstyle:VisibilityModifier", "java:S1104"}) +public class Address +{ + public int number; + public String street; + public String city; +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/BusinessBranch.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/BusinessBranch.java new file mode 100644 index 0000000..6e8151f --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/BusinessBranch.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.v1_and_higher; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + + +@SuppressWarnings("checkstyle:VisibilityModifier") +public class BusinessBranch +{ + public final List customers = new ArrayList<>(); + + @Override + public String toString() + { + return "Branch v1 and higher\n" + + "Customers:\n" + + this.customers.stream() + .map(c -> c.name) + .collect(Collectors.joining("\n")); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/Customer.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/Customer.java new file mode 100644 index 0000000..5f910c8 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/practical/v1_and_higher/Customer.java @@ -0,0 +1,23 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.practical.v1_and_higher; + +@SuppressWarnings({"checkstyle:VisibilityModifier", "java:S1104"}) +public class Customer +{ + public String name; + public Address address = new Address(); +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/MainReflective.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/MainReflective.java new file mode 100644 index 0000000..aa82490 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/MainReflective.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.reflective; + +import java.util.Date; +import java.util.logging.Logger; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.migrater.reflection.ReflectiveMigrater; +import software.xdev.micromigration.migrater.reflection.ScriptInstantiationException; + + +/** + * Shows the usage of the {@link ReflectiveMigrater}. Very simple. + */ +@SuppressWarnings("java:S2629") +public final class MainReflective +{ + public static void main(final String[] args) + { + try + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.examples.reflective.scripts"); + final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start(migrater); + Logger.getGlobal().info(storageManager.root().toString()); + if(storageManager.root() == null) + { + storageManager.setRoot("Hello World! @ " + new Date()); + } + storageManager.storeRoot(); + storageManager.shutdown(); + } + catch(final IllegalArgumentException | SecurityException | ScriptInstantiationException e) + { + throw new IllegalStateException("Could not initiate migration script", e); + } + } + + private MainReflective() + { + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/scripts/UpdateToV1_0.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/scripts/UpdateToV1_0.java new file mode 100644 index 0000000..0dac442 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/scripts/UpdateToV1_0.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.reflective.scripts; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV1_0 implements MigrationScript +{ + private static final Logger LOG = LoggerFactory.getLogger(UpdateToV1_0.class); + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 0); + } + + @Override + public void migrate(final Context context) + { + LOG.info("Update {} executed", this.getTargetVersion()); + context.getStorageManager().setRoot("Hello World! @ " + new Date() + " Update 1.0"); + } +} diff --git a/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/scripts/UpdateToV1_1.java b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/scripts/UpdateToV1_1.java new file mode 100644 index 0000000..7069ed1 --- /dev/null +++ b/micro-migration-demo/src/main/java/software/xdev/micromigration/examples/reflective/scripts/UpdateToV1_1.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2021 XDEV Software GmbH (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.examples.reflective.scripts; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationScript; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.version.MigrationVersion; + + +@SuppressWarnings({"checkstyle:TypeName", "java:S101"}) +public class UpdateToV1_1 implements MigrationScript +{ + private static final Logger LOG = LoggerFactory.getLogger(UpdateToV1_1.class); + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1, 1); + } + + @Override + public void migrate(final Context context) + { + LOG.info("Update {} executed", this.getTargetVersion()); + context.getStorageManager().setRoot("Hello World! @ " + new Date() + " Update 1.1"); + } +} diff --git a/template-placeholder/pom.xml b/micro-migration/pom.xml similarity index 86% rename from template-placeholder/pom.xml rename to micro-migration/pom.xml index 3c96888..66c2258 100644 --- a/template-placeholder/pom.xml +++ b/micro-migration/pom.xml @@ -5,20 +5,20 @@ 4.0.0 software.xdev - template-placeholder - 1.0.0-SNAPSHOT + micro-migration + 2.0.1-SNAPSHOT jar - template-placeholder - template-placeholder - https://github.com/xdev-software/template-placeholder + micro-migration + micro-migration + https://github.com/xdev-software/micro-migration - https://github.com/xdev-software/template-placeholder - scm:git:https://github.com/xdev-software/template-placeholder.git + https://github.com/xdev-software/micro-migration + scm:git:https://github.com/xdev-software/micro-migration.git - 2023 + 2021 XDEV Software @@ -84,6 +84,33 @@ + + + org.eclipse.store + storage-embedded + 1.3.2 + + + org.eclipse.store + storage-embedded-configuration + 1.3.2 + + + + org.junit.jupiter + junit-jupiter + 5.10.3 + test + + + + org.slf4j + slf4j-simple + 2.0.13 + test + + + @@ -172,6 +199,12 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + 3.3.0 + diff --git a/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationEmbeddedStorage.java b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationEmbeddedStorage.java new file mode 100644 index 0000000..52bdb7e --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationEmbeddedStorage.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore; + +import java.nio.file.Path; +import java.util.Objects; + +import org.eclipse.store.afs.nio.types.NioFileSystem; +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.types.Storage; +import org.eclipse.store.storage.types.StorageConfiguration; + +import software.xdev.micromigration.migrater.MicroMigrater; + + +/** + * Provides static utility calls to create the {@link MigrationEmbeddedStorageManager} for updateable datastores. + * Basically a wrapper for the utility class {@link EmbeddedStorage}. + */ +public final class MigrationEmbeddedStorage +{ + /** + * Creates a {@link MigrationEmbeddedStorageManager} with the given {@link MicroMigrater}. Uses the + * {@link EmbeddedStorageFoundation#New()} configuration for the actual {@link EmbeddedStorageManager}. + *

Warning "resource" is suppressed because it is used and closed in the + * {@link MigrationEmbeddedStorageManager}. + * + * @param migrater which is used as source for the migration scripts + * @return the created storage manager with the given migrater + */ + @SuppressWarnings("java:S2095") + public static MigrationEmbeddedStorageManager start(final MicroMigrater migrater) + { + Objects.requireNonNull(migrater); + return new MigrationEmbeddedStorageManager( + createStorageManager(), + migrater + ).start(); + } + + /** + * Creates a {@link MigrationEmbeddedStorageManager} with the given {@link MicroMigrater}. Uses the + * {@link EmbeddedStorageFoundation#New()} configuration for the actual {@link EmbeddedStorageManager}. + *

Warning "resource" is suppressed because it is used and closed in the + * {@link MigrationEmbeddedStorageManager}. + * + * @param storageDirectory is used as the base directory for the datastore + * @param migrater which is used as source for the migration scripts + * @return the created storage manager with the given migrater + */ + @SuppressWarnings("java:S2095") + public static MigrationEmbeddedStorageManager start( + final Path storageDirectory, + final MicroMigrater migrater + ) + { + Objects.requireNonNull(migrater); + Objects.requireNonNull(storageDirectory); + + return new MigrationEmbeddedStorageManager( + createStorageManager(storageDirectory), + migrater + ).start(); + } + + private static EmbeddedStorageManager createStorageManager(final Path storageDirectory) + { + final NioFileSystem fileSystem = NioFileSystem.New(); + return EmbeddedStorageFoundation.New() + .setConfiguration( + StorageConfiguration.Builder() + .setStorageFileProvider( + Storage.FileProviderBuilder(fileSystem) + .setDirectory(fileSystem.ensureDirectoryPath(storageDirectory.toAbsolutePath().toString())) + .createFileProvider() + ) + .createConfiguration() + ) + .createEmbeddedStorageManager(); + } + + private static EmbeddedStorageManager createStorageManager() + { + return EmbeddedStorageFoundation.New() + .setConfiguration( + StorageConfiguration.Builder().createConfiguration() + ) + .createEmbeddedStorageManager(); + } + + private MigrationEmbeddedStorage() + { + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationEmbeddedStorageManager.java b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationEmbeddedStorageManager.java new file mode 100644 index 0000000..61eddee --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationEmbeddedStorageManager.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +import software.xdev.micromigration.migrater.MicroMigrater; +import software.xdev.micromigration.version.Versioned; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Specific implementation of the {@link VersionAgnosticMigrationEmbeddedStorageManager} for one specific version. + * @see VersionAgnosticMigrationEmbeddedStorageManager + */ +public class MigrationEmbeddedStorageManager + extends VersionAgnosticMigrationEmbeddedStorageManager +{ + /** + * @param nativeManager which will be used as the underlying storage manager. Almost all methods are only rerouted + * to this native manager. Only {@link #start()}, {@link #root()} and {@link #setRoot(Object)} + * are intercepted and a {@link Versioned} is placed between the requests. + * @param migrater which is used as source for the migration scripts + */ + public MigrationEmbeddedStorageManager( + final EmbeddedStorageManager nativeManager, + final MicroMigrater migrater + ) + { + super(new TunnelingEmbeddedStorageManager(nativeManager), migrater); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationManager.java b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationManager.java new file mode 100644 index 0000000..34edbf3 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationManager.java @@ -0,0 +1,86 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; + +import software.xdev.micromigration.migrater.MicroMigrater; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.version.Versioned; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationManager; + + +/** + * Specific implementation of the {@link VersionAgnosticMigrationManager}. + * + * @see VersionAgnosticMigrationManager + */ +public class MigrationManager extends VersionAgnosticMigrationManager +{ + /** + * Much more complicated constructor than + * {@link MigrationManager#MigrationManager(Versioned, MicroMigrater, EmbeddedStorageManager)} + * + * @param currentVersionGetter which supplies the current version of the object to update. + * @param currentVersionSetter which sets the new version of the object in some membervariable. This Consumer is + * not + * supposed to store the version, but only save it in some membervariable to be stored + * after. + * @param currentVersionStorer which is supposed to store the new version of the object somewhere in the datastore. + * @param migrater does the actual migration with the given {@link VersionAgnosticMigrationScript} + * @param storageManager for the {@link VersionAgnosticMigrationScript}s to use. Is not used for the storing + * of the new version. + */ + public MigrationManager( + final Supplier currentVersionGetter, + final Consumer currentVersionSetter, + final Consumer currentVersionStorer, + final MicroMigrater migrater, + final EmbeddedStorageManager storageManager + ) + { + super( + currentVersionGetter, + currentVersionSetter, + currentVersionStorer, + migrater, + new MigrationEmbeddedStorageManager(storageManager, migrater)); + } + + /** + * Simple Constructor. + * + * @param versionedObject which provides getter and setter for the current version. This object will be stored + * after + * the {@link VersionAgnosticMigrationScript}s are executed. + * @param migrater does the actual migration with the given {@link VersionAgnosticMigrationScript} + * @param storageManager for the {@link VersionAgnosticMigrationScript}s to use. Is not used for the storing of + * the + * new version. + */ + public MigrationManager( + final Versioned versionedObject, + final MicroMigrater migrater, + final EmbeddedStorageManager storageManager + ) + { + super(versionedObject, migrater, new MigrationEmbeddedStorageManager(storageManager, migrater)); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationScript.java b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationScript.java new file mode 100644 index 0000000..111e008 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/MigrationScript.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore; + +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; + + +/** + * Interface for scripts to migrate / update datastores. + *

+ * One script is supposed to bring a datastore from a lower version to the target version. After the + * {@link VersionAgnosticMigrationScript#migrate(Context)} method is called, the target version is reached. + *

+ * This is a shorthand for {@link VersionAgnosticMigrationScript} + */ +public interface MigrationScript extends VersionAgnosticMigrationScript +{ +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/TunnelingEmbeddedStorageManager.java b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/TunnelingEmbeddedStorageManager.java new file mode 100644 index 0000000..1bb2984 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/eclipsestore/TunnelingEmbeddedStorageManager.java @@ -0,0 +1,418 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore; + +import java.nio.ByteBuffer; +import java.util.Objects; +import java.util.function.Predicate; + +import org.eclipse.serializer.afs.types.AFile; +import org.eclipse.serializer.collections.types.XGettingEnum; +import org.eclipse.serializer.persistence.binary.types.Binary; +import org.eclipse.serializer.persistence.types.PersistenceManager; +import org.eclipse.serializer.persistence.types.PersistenceRootsView; +import org.eclipse.serializer.persistence.types.PersistenceTypeDictionaryExporter; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.eclipse.store.storage.types.Database; +import org.eclipse.store.storage.types.StorageConfiguration; +import org.eclipse.store.storage.types.StorageConnection; +import org.eclipse.store.storage.types.StorageEntityCacheEvaluator; +import org.eclipse.store.storage.types.StorageEntityTypeExportFileProvider; +import org.eclipse.store.storage.types.StorageEntityTypeExportStatistics; +import org.eclipse.store.storage.types.StorageEntityTypeHandler; +import org.eclipse.store.storage.types.StorageLiveFileProvider; +import org.eclipse.store.storage.types.StorageRawFileStatistics; +import org.eclipse.store.storage.types.StorageTypeDictionary; + +import software.xdev.micromigration.version.Versioned; +import software.xdev.micromigration.versionagnostic.VersionAgnosticTunnelingEmbeddedStorageManager; + + +/** + * Wrapper class for the {@link EmbeddedStorageManager} interface. + *

+ * It simply relays all the commands to the contained {@link EmbeddedStorageManager}. + * @see VersionAgnosticTunnelingEmbeddedStorageManager + */ +public class TunnelingEmbeddedStorageManager + implements + EmbeddedStorageManager, + VersionAgnosticTunnelingEmbeddedStorageManager +{ + /** + * The underlying, actual EmbeddedStorageManager + */ + protected final EmbeddedStorageManager nativeManager; + + /** + * @param nativeManager which will be used as the underlying storage manager. All methods are only rerouted to this + * native manager. Only {@link #start()}, {@link #root()} and {@link #setRoot(Object)} are + * intercepted and a {@link Versioned} is placed between the requests. + */ + public TunnelingEmbeddedStorageManager( + final EmbeddedStorageManager nativeManager + ) + { + Objects.requireNonNull(nativeManager); + this.nativeManager = nativeManager; + } + + //////////////////////////////////////////////////////////////// + // Simply forward all the methods + //////////////////////////////////////////////////////////////// + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#start} + */ + @Override + public TunnelingEmbeddedStorageManager start() + { + this.nativeManager.start(); + return this; + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#root} + */ + @Override + public Object root() + { + return this.nativeManager.root(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#setRoot(Object)} + */ + @Override + public Object setRoot(final Object newRoot) + { + return this.nativeManager.setRoot(newRoot); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#storeRoot()} + */ + @Override + public long storeRoot() + { + return this.nativeManager.storeRoot(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#configuration()} + */ + @Override + public StorageConfiguration configuration() + { + return this.nativeManager.configuration(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#typeDictionary()} + */ + @Override + public StorageTypeDictionary typeDictionary() + { + return this.nativeManager.typeDictionary(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#shutdown()} + */ + @Override + public boolean shutdown() + { + return this.nativeManager.shutdown(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#close()} + */ + @Override + public void close() + { + this.nativeManager.close(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#createConnection()} + */ + @Override + public StorageConnection createConnection() + { + return this.nativeManager.createConnection(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#viewRoots()} + */ + @Override + public PersistenceRootsView viewRoots() + { + return this.nativeManager.viewRoots(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#database()} + */ + @Override + public Database database() + { + return this.nativeManager.database(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#isAcceptingTasks()} + */ + @Override + public boolean isAcceptingTasks() + { + return this.nativeManager.isAcceptingTasks(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#isRunning()} + */ + @Override + public boolean isRunning() + { + return this.nativeManager.isRunning(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#isStartingUp()} + */ + @Override + public boolean isStartingUp() + { + return this.nativeManager.isStartingUp(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#isShuttingDown()} + */ + @Override + public boolean isShuttingDown() + { + return this.nativeManager.isShuttingDown(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#checkAcceptingTasks()} + */ + @Override + public void checkAcceptingTasks() + { + this.nativeManager.checkAcceptingTasks(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#initializationTime()} + */ + @Override + public long initializationTime() + { + return this.nativeManager.initializationTime(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#operationModeTime()} + */ + @Override + public long operationModeTime() + { + return this.nativeManager.operationModeTime(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#isActive()} + */ + @Override + public boolean isActive() + { + return this.nativeManager.isActive(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#issueGarbageCollection(long)} + */ + @Override + public boolean issueGarbageCollection(final long nanoTimeBudget) + { + return this.nativeManager.issueGarbageCollection(nanoTimeBudget); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#issueFileCheck(long)} + */ + @Override + public boolean issueFileCheck(final long nanoTimeBudget) + { + return this.nativeManager.issueFileCheck(nanoTimeBudget); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#issueCacheCheck(long, StorageEntityCacheEvaluator)} + */ + @Override + public boolean issueCacheCheck(final long nanoTimeBudget, final StorageEntityCacheEvaluator entityEvaluator) + { + return this.nativeManager.issueCacheCheck(nanoTimeBudget, entityEvaluator); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#createStorageStatistics} + */ + @Override + public StorageRawFileStatistics createStorageStatistics() + { + return this.nativeManager.createStorageStatistics(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#exportChannels(StorageLiveFileProvider)} + */ + @Override + public void exportChannels(final StorageLiveFileProvider fileProvider, final boolean performGarbageCollection) + { + this.nativeManager.exportChannels(fileProvider, performGarbageCollection); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#exportTypes(StorageEntityTypeExportFileProvider)} + */ + @Override + public StorageEntityTypeExportStatistics exportTypes( + final StorageEntityTypeExportFileProvider exportFileProvider, + final Predicate isExportType) + { + return this.nativeManager.exportTypes(exportFileProvider, isExportType); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#importFiles(XGettingEnum)} + */ + @Override + public void importFiles(final XGettingEnum importFiles) + { + this.nativeManager.importFiles(importFiles); + } + + @Override + public void importData(final XGettingEnum xGettingEnum) + { + this.nativeManager.importData(xGettingEnum); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#persistenceManager()} + */ + @Override + public PersistenceManager persistenceManager() + { + return this.nativeManager.persistenceManager(); + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#store(Object)} + */ + @Override + public long store(final Object instance) + { + return EmbeddedStorageManager.super.store(instance); + } + + @Override + public EmbeddedStorageManager getNativeStorageManager() + { + return this.nativeManager; + } + + /** + * Simply tunneling the call through to the {@link EmbeddedStorageManager} given through the constructor. Please + * see + * {@link EmbeddedStorageManager#issueFullBackup(StorageLiveFileProvider, PersistenceTypeDictionaryExporter)} + */ + @Override + public void issueFullBackup( + final StorageLiveFileProvider targetFileProvider, + final PersistenceTypeDictionaryExporter typeDictionaryExporter) + { + this.nativeManager.issueFullBackup(targetFileProvider, typeDictionaryExporter); + } + + @Override + public void issueTransactionsLogCleanup() + { + this.nativeManager.issueTransactionsLogCleanup(); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/migrater/AbstractMigrater.java b/micro-migration/src/main/java/software/xdev/micromigration/migrater/AbstractMigrater.java new file mode 100644 index 0000000..bbf0d71 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/migrater/AbstractMigrater.java @@ -0,0 +1,168 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater; + +import java.time.Clock; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.TreeSet; +import java.util.function.Consumer; + +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithScriptReference; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Provides the basic functionality to apply {@link VersionAgnosticMigrationScript}s to a datastore. + */ +public abstract class AbstractMigrater implements MicroMigrater +{ + private final List> notificationConsumers = + new ArrayList<>(); + private Clock clock = Clock.systemDefaultZone(); + + @Override + public void registerNotificationConsumer( + final Consumer notificationConsumer) + { + this.notificationConsumers.add(notificationConsumer); + } + + @Override + public > MigrationVersion migrateToNewest( + final MigrationVersion fromVersion, + final E storageManager, + final Object root + ) + { + Objects.requireNonNull(fromVersion); + Objects.requireNonNull(storageManager); + + final TreeSet> sortedScripts = this.getSortedScripts(); + if(!sortedScripts.isEmpty()) + { + return this.migrateToVersion( + fromVersion, + this.getSortedScripts().last().getTargetVersion(), + storageManager, + root + ); + } + return fromVersion; + } + + @SuppressWarnings("unchecked") + @Override + public > MigrationVersion migrateToVersion( + final MigrationVersion fromVersion, + final MigrationVersion targetVersion, + final E storageManager, + final Object objectToMigrate + ) + { + Objects.requireNonNull(fromVersion); + Objects.requireNonNull(targetVersion); + Objects.requireNonNull(storageManager); + + MigrationVersion updateVersionWhichWasExecuted = fromVersion; + for(final VersionAgnosticMigrationScript script : this.getSortedScripts()) + { + final VersionAgnosticMigrationScript castedScript = (VersionAgnosticMigrationScript)script; + if(MigrationVersion.COMPARATOR.compare(fromVersion, script.getTargetVersion()) < 0 + && MigrationVersion.COMPARATOR.compare(script.getTargetVersion(), targetVersion) <= 0) + { + LocalDateTime startDate = null; + final MigrationVersion versionBeforeUpdate = updateVersionWhichWasExecuted; + if(!this.notificationConsumers.isEmpty()) + { + startDate = LocalDateTime.now(this.clock); + } + updateVersionWhichWasExecuted = + this.migrateWithScript(castedScript, storageManager, objectToMigrate); + if(!this.notificationConsumers.isEmpty()) + { + final ScriptExecutionNotificationWithScriptReference scriptNotification = + new ScriptExecutionNotificationWithScriptReference( + script, + versionBeforeUpdate, + updateVersionWhichWasExecuted, + startDate, + LocalDateTime.now(this.clock) + ); + this.notificationConsumers.forEach(consumer -> consumer.accept(scriptNotification)); + } + } + } + return updateVersionWhichWasExecuted; + } + + @SuppressWarnings("unchecked") + private > MigrationVersion migrateWithScript( + final VersionAgnosticMigrationScript script, + final E storageManager, + final Object objectToMigrate + ) + { + final T castedObjectToMigrate = (T)objectToMigrate; + script.migrate(new Context<>(castedObjectToMigrate, storageManager)); + return script.getTargetVersion(); + } + + /** + * Checks if the given {@link VersionAgnosticMigrationScript} is not already registered in the + * {@link #getSortedScripts()}. + * + * @param scriptToCheck It's target version is checked, if it is not already registered. + * @throws VersionAlreadyRegisteredException if script is already registered. + */ + protected void checkIfVersionIsAlreadyRegistered(final VersionAgnosticMigrationScript scriptToCheck) + { + // Check if same version is not already registered + for(final VersionAgnosticMigrationScript alreadyRegisteredScript : this.getSortedScripts()) + { + if(MigrationVersion.COMPARATOR.compare( + alreadyRegisteredScript.getTargetVersion(), + scriptToCheck.getTargetVersion()) == 0) + { + // Two scripts with the same version are not allowed to get registered. + throw new VersionAlreadyRegisteredException( + alreadyRegisteredScript.getTargetVersion(), + alreadyRegisteredScript, + scriptToCheck + ); + } + } + } + + /** + * Change used clock for notifications from {@link #registerNotificationConsumer(Consumer)}. + * + * @param clock is used when a + * {@link software.xdev.micromigration.notification.ScriptExecutionNotificationWithoutScriptReference} + * is created + * @return self + */ + public AbstractMigrater withClock(final Clock clock) + { + this.clock = clock; + return this; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/migrater/ExplicitMigrater.java b/micro-migration/src/main/java/software/xdev/micromigration/migrater/ExplicitMigrater.java new file mode 100644 index 0000000..29f1170 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/migrater/ExplicitMigrater.java @@ -0,0 +1,55 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater; + +import java.util.TreeSet; + +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; + + +/** + * Contains all the available scripts to migrate the datastore to a certain version. + *

+ * This class needs explicit scripts which are then included in the migration process. + */ +public class ExplicitMigrater extends AbstractMigrater +{ + private final TreeSet> sortedScripts = new TreeSet<>( + VersionAgnosticMigrationScript.COMPARATOR); + + /** + * @param scripts are all the scripts that are executed, if the current version is lower than this of the + * script
+ * Versions of the scripts must be unique. That means that no version is allowed multiple times in + * the migrater. + * @throws VersionAlreadyRegisteredException if two scripts have the same version + */ + @SuppressWarnings("PMD.UseArraysAsList") + public ExplicitMigrater(final VersionAgnosticMigrationScript... scripts) + { + for(final VersionAgnosticMigrationScript script : scripts) + { + this.checkIfVersionIsAlreadyRegistered(script); + this.sortedScripts.add(script); + } + } + + @Override + public TreeSet> getSortedScripts() + { + return this.sortedScripts; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/migrater/MicroMigrater.java b/micro-migration/src/main/java/software/xdev/micromigration/migrater/MicroMigrater.java new file mode 100644 index 0000000..7cf747e --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/migrater/MicroMigrater.java @@ -0,0 +1,104 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater; + +import java.util.TreeSet; +import java.util.function.Consumer; + +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithScriptReference; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Executes all the available scripts to migrate the datastore to a certain version. + */ +public interface MicroMigrater +{ + /** + * @return all the contained {@link VersionAgnosticMigrationScript}s, sorted by their {@link MigrationVersion} + * ascending. + */ + @SuppressWarnings("java:S1452") + TreeSet> getSortedScripts(); + + /** + * Executes all the scripts that are available to the migrater. Only scripts with a higher target version than the + * given fromVersion are executed.
Scripts are executed one after another from the lowest to the highest + * version. + *

+ * Example:
+ * Current version is 1.0.0
Scripts for v1.1.0, v2.0.0 and v1.2.1 are available
Scripts are chain executed + * like v1.1.0 then v1.2.1 then v2.0.0 + * + * @param fromVersion is the current version of the datastore. Scripts for lower versions then the fromVersion + * are not executed. + * @param storageManager is relayed to the scripts {@link VersionAgnosticMigrationScript#migrate(Context)} method. + * This way the script can call + * {@link VersionAgnosticMigrationEmbeddedStorageManager#store(Object)} or another method on + * the storage manager. + * @param root is relayed to the scripts {@link VersionAgnosticMigrationScript#migrate(Context)} method. + * This way the script can change something within the root object. + * @param the {@link VersionAgnosticMigrationEmbeddedStorageManager} which contains the migrating + * object + * @return the target version of the last executed script + */ + > MigrationVersion migrateToNewest( + MigrationVersion fromVersion, + E storageManager, + Object root + ); + + /** + * Executes all the scripts that are available to the migrater until the given targetVersion is reached. Only + * scripts with a higher target version than the given fromVersion are executed.
Scripts are executed one after + * another from the lowest to the highest version. + *

+ * Example:
+ * Current version is 1.0.0
Scripts for v1.1.0, v2.0.0 and v1.2.1 are available
Scripts are chain executed + * like v1.1.0 then v1.2.1 then v2.0.0 + * + * @param fromVersion is the current version of the datastore. Scripts for lower versions then the fromVersion + * are not executed. + * @param targetVersion is the highest allowed script version. Scripts which have a higher version won't be + * exectued. + * @param storageManager is relayed to the scripts {@link VersionAgnosticMigrationScript#migrate(Context)} method. + * This way the script can call EmbeddedStorageManager#store or another method on the + * storage + * manager. + * @param objectToMigrate is relayed to the scripts {@link VersionAgnosticMigrationScript#migrate(Context)} method. + * This way the script can change something within the object to migrate. + * @param the {@link VersionAgnosticMigrationEmbeddedStorageManager} which contains the migrating + * object + * @return the target version of the last executed script + */ + > MigrationVersion migrateToVersion( + MigrationVersion fromVersion, + MigrationVersion targetVersion, + E storageManager, + Object objectToMigrate + ); + + /** + * Registers a callback to take action when a script is executed. + * + * @param notificationConsumer is executed when a script is used from this migrater. + */ + void registerNotificationConsumer( + Consumer notificationConsumer); +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/migrater/VersionAlreadyRegisteredException.java b/micro-migration/src/main/java/software/xdev/micromigration/migrater/VersionAlreadyRegisteredException.java new file mode 100644 index 0000000..f10ce22 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/migrater/VersionAlreadyRegisteredException.java @@ -0,0 +1,86 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater; + +import java.util.Objects; + +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +/** + * Exception that should be used if two scripts with the same version exist. + */ +@SuppressWarnings({"java:S1948", "java:S1452"}) +public class VersionAlreadyRegisteredException extends RuntimeException +{ + /** + * The already registered script with the same version + */ + private final MigrationVersion alreadyRegisteredVersion; + /** + * The version of the already registered script + */ + private final VersionAgnosticMigrationScript alreadyRegisteredScript; + /** + * The script with the same version as {@link #alreadyRegisteredScript}, which should be registered as well + */ + private final VersionAgnosticMigrationScript newScriptToRegister; + + /** + * @param alreadyRegisteredVersion The version of the already registered script + * @param alreadyRegisteredScript The already registered script with the same version + * @param newScriptToRegister The script with the same version as alreadyRegisteredScript, which should be + * registered as well + */ + public VersionAlreadyRegisteredException( + final MigrationVersion alreadyRegisteredVersion, + final VersionAgnosticMigrationScript alreadyRegisteredScript, + final VersionAgnosticMigrationScript newScriptToRegister + ) + { + super("Version " + alreadyRegisteredVersion.toString() + + " is already registered. Versions must be unique within the migrater."); + this.alreadyRegisteredVersion = Objects.requireNonNull(alreadyRegisteredVersion); + this.alreadyRegisteredScript = Objects.requireNonNull(alreadyRegisteredScript); + this.newScriptToRegister = Objects.requireNonNull(newScriptToRegister); + } + + /** + * @return the version of the already registered script + */ + public MigrationVersion getAlreadyRegisteredVersion() + { + return this.alreadyRegisteredVersion; + } + + /** + * @return the already registered script with the same version + */ + public VersionAgnosticMigrationScript getAlreadyRegisteredScript() + { + return this.alreadyRegisteredScript; + } + + /** + * @return the script with the same version as {@link #getAlreadyRegisteredScript()}, which should be registered as + * well + */ + public VersionAgnosticMigrationScript getNewScriptToRegister() + { + return this.newScriptToRegister; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/migrater/reflection/ReflectiveMigrater.java b/micro-migration/src/main/java/software/xdev/micromigration/migrater/reflection/ReflectiveMigrater.java new file mode 100644 index 0000000..49210df --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/migrater/reflection/ReflectiveMigrater.java @@ -0,0 +1,166 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.TreeSet; + +import software.xdev.micromigration.migrater.AbstractMigrater; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; + + +/** + * Contains all the available scripts to migrate the datastore to a certain version. + *

+ * Searches all implementation of {@link VersionAgnosticMigrationScript} in the specified package and it's the sub + * packages. + *

+ *

+ * Reflection source: https://stackoverflow.com/a/520344 + *

+ * @author AB + */ +public class ReflectiveMigrater extends AbstractMigrater +{ + private static final String CLASS_EXTENSION = ".class"; + + private final TreeSet> sortedScripts = new TreeSet<>( + VersionAgnosticMigrationScript.COMPARATOR); + + /** + * @param packagePath defines the package in which {@link VersionAgnosticMigrationScript}s will be searched. Also + * searches through all sub packages of packagePath + * @throws ScriptInstantiationException if a class in the given package could not be instantiated + */ + @SuppressWarnings("unchecked") + public ReflectiveMigrater(final String packagePath) + { + getClasses(packagePath) + .stream() + .filter(c -> !Modifier.isAbstract(c.getModifiers())) + .filter(VersionAgnosticMigrationScript.class::isAssignableFrom) + .map(c -> (Class)c) + .map(this::instantiateClass) + .forEach(instantiateScript -> { + this.checkIfVersionIsAlreadyRegistered(instantiateScript); + this.sortedScripts.add(instantiateScript); + }); + } + + @SuppressWarnings("rawtypes") + private VersionAgnosticMigrationScript instantiateClass( + final Class scriptClass) + { + try + { + return scriptClass.getDeclaredConstructor().newInstance(); + } + catch(final InstantiationException + | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException + | NoSuchMethodException + | SecurityException e + ) + { + throw new ScriptInstantiationException("Could not instantiate class " + scriptClass.getName(), e); + } + } + + /** + * Scans all classes accessible from the context class loader which belong to the given package and subpackages. + * + * @param packageName The base package + * @return The classes + */ + private static List> getClasses(final String packageName) + { + try + { + final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + assert classLoader != null; + final String path = packageName.replace('.', '/'); + final Enumeration resources = classLoader.getResources(path); + final List dirs = new ArrayList<>(); + while(resources.hasMoreElements()) + { + final URL resource = resources.nextElement(); + dirs.add(new File(resource.getFile())); + } + final ArrayList> classes = new ArrayList<>(); + for(final File directory : dirs) + { + classes.addAll(findClasses(directory, packageName)); + } + return classes; + } + catch(final ClassNotFoundException e) + { + throw new IllegalStateException("Unable to find class", e); + } + catch(final IOException ioe) + { + throw new UncheckedIOException(ioe); + } + } + + /** + * Recursive method used to find all classes in a given directory and subdirs. + * + * @param directory The base directory + * @param packageName The package name for classes found inside the base directory + * @return The classes + */ + private static List> findClasses(final File directory, final String packageName) + throws ClassNotFoundException + { + if(!directory.exists()) + { + return new ArrayList<>(); + } + + final List> classes = new ArrayList<>(); + for(final File file : directory.listFiles()) + { + if(file.isDirectory()) + { + assert !file.getName().contains("."); + classes.addAll(findClasses(file, packageName + "." + file.getName())); + } + else if(file.getName().endsWith(CLASS_EXTENSION)) + { + classes.add(Class.forName( + packageName + '.' + file.getName() + .substring(0, file.getName().length() - CLASS_EXTENSION.length()))); + } + } + return classes; + } + + @Override + public TreeSet> getSortedScripts() + { + return this.sortedScripts; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/migrater/reflection/ScriptInstantiationException.java b/micro-migration/src/main/java/software/xdev/micromigration/migrater/reflection/ScriptInstantiationException.java new file mode 100644 index 0000000..3377adf --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/migrater/reflection/ScriptInstantiationException.java @@ -0,0 +1,31 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection; + +/** + * Holds information about exceptions if a script class can not be instantiated. + */ +public class ScriptInstantiationException extends RuntimeException +{ + /** + * @param message for the exception + * @param cause of the exception + */ + public ScriptInstantiationException(final String message, final Throwable cause) + { + super(message, cause); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/notification/AbstractScriptExecutionNotification.java b/micro-migration/src/main/java/software/xdev/micromigration/notification/AbstractScriptExecutionNotification.java new file mode 100644 index 0000000..0513fd5 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/notification/AbstractScriptExecutionNotification.java @@ -0,0 +1,85 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.notification; + +import java.time.LocalDateTime; + +import software.xdev.micromigration.migrater.MicroMigrater; +import software.xdev.micromigration.version.MigrationVersion; + + +/** + * Contains data about the execution of a script by a {@link MicroMigrater}. + */ +public abstract class AbstractScriptExecutionNotification +{ + private final MigrationVersion sourceVersion; + private final MigrationVersion targetVersion; + private final LocalDateTime startDate; + private final LocalDateTime endDate; + + /** + * @param sourceVersion original version of the object before executing the script + * @param targetVersion version of the object after executing the script + * @param startDate time when the script was started + * @param endDate time when the script has finished + */ + protected AbstractScriptExecutionNotification( + final MigrationVersion sourceVersion, + final MigrationVersion targetVersion, + final LocalDateTime startDate, + final LocalDateTime endDate + ) + { + super(); + this.sourceVersion = sourceVersion; + this.targetVersion = targetVersion; + this.startDate = startDate; + this.endDate = endDate; + } + + /** + * @return the original version of the object before executing the script + */ + public MigrationVersion getSourceVersion() + { + return this.sourceVersion; + } + + /** + * @return the version of the object after executing the script + */ + public MigrationVersion getTargetVersion() + { + return this.targetVersion; + } + + /** + * @return the time when the script was started + */ + public LocalDateTime getStartDate() + { + return this.startDate; + } + + /** + * @return time when the script has finished + */ + public LocalDateTime getEndDate() + { + return this.endDate; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/notification/ScriptExecutionNotificationWithScriptReference.java b/micro-migration/src/main/java/software/xdev/micromigration/notification/ScriptExecutionNotificationWithScriptReference.java new file mode 100644 index 0000000..8affdf4 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/notification/ScriptExecutionNotificationWithScriptReference.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.notification; + +import java.time.LocalDateTime; + +import software.xdev.micromigration.migrater.MicroMigrater; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +/** + * Contains data about the execution of a script by a {@link MicroMigrater}. + */ +public class ScriptExecutionNotificationWithScriptReference extends AbstractScriptExecutionNotification +{ + private final VersionAgnosticMigrationScript executedScript; + + /** + * @param executedScript script that was executed + * @param sourceVersion original version of the object before executing the script + * @param targetVersion version of the object after executing the script + * @param startDate time when the script was started + * @param endDate time when the script has finished + */ + public ScriptExecutionNotificationWithScriptReference( + final VersionAgnosticMigrationScript executedScript, + final MigrationVersion sourceVersion, + final MigrationVersion targetVersion, + final LocalDateTime startDate, + final LocalDateTime endDate + ) + { + super( + sourceVersion, + targetVersion, + startDate, + endDate + ); + this.executedScript = executedScript; + } + + /** + * @return the script that was executed + */ + @SuppressWarnings("java:S1452") + public VersionAgnosticMigrationScript getExecutedScript() + { + return this.executedScript; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/notification/ScriptExecutionNotificationWithoutScriptReference.java b/micro-migration/src/main/java/software/xdev/micromigration/notification/ScriptExecutionNotificationWithoutScriptReference.java new file mode 100644 index 0000000..cacf6f9 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/notification/ScriptExecutionNotificationWithoutScriptReference.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.notification; + +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; + +/** + * Same as {@link ScriptExecutionNotificationWithScriptReference} but instead of referencing + * the {@link VersionAgnosticMigrationScript} directly, only the name of the script is + * extracted through the class name. + *

+ * "Why?!" - If you want to persist say a history of your applied scripts in your database and + * you reference your scripts directly, these classes are referenced in your datastore. + * That shouldn't be a problem. Except when you refactor or delete these scripts. + * Usually what's really important is the name of the script. + */ +public class ScriptExecutionNotificationWithoutScriptReference extends AbstractScriptExecutionNotification +{ + private final String executedScriptName; + + /** + * @param originalNotification where the reference to the script is deleted and the class name is extracted. + */ + public ScriptExecutionNotificationWithoutScriptReference( + final ScriptExecutionNotificationWithScriptReference originalNotification) + { + super( + originalNotification.getSourceVersion(), + originalNotification.getTargetVersion(), + originalNotification.getStartDate(), + originalNotification.getEndDate() + ); + this.executedScriptName = originalNotification.getExecutedScript().getClass().getSimpleName(); + } + + /** + * @return the name of the script that was extracted. + */ + public String getExecutedScriptName() + { + return this.executedScriptName; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/scripts/Context.java b/micro-migration/src/main/java/software/xdev/micromigration/scripts/Context.java new file mode 100644 index 0000000..9525de7 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/scripts/Context.java @@ -0,0 +1,55 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.scripts; + +/** + * Container that holds necessary information for the execution of an {@link VersionAgnosticMigrationScript} + */ +public class Context +{ + private final T migratingObject; + private final E storageManager; + + /** + * @param migratingObject that must be migrated to a new version + * @param storageManager where the migratingObject is stored + */ + public Context( + final T migratingObject, + final E storageManager + ) + { + super(); + this.migratingObject = migratingObject; + this.storageManager = storageManager; + } + + /** + * @return the current object where the migration is executed upon + */ + public T getMigratingObject() + { + return this.migratingObject; + } + + /** + * @return the responsible storage manager for the migrating object + */ + public E getStorageManager() + { + return this.storageManager; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/scripts/ReflectiveVersionMigrationScript.java b/micro-migration/src/main/java/software/xdev/micromigration/scripts/ReflectiveVersionMigrationScript.java new file mode 100644 index 0000000..b2d1511 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/scripts/ReflectiveVersionMigrationScript.java @@ -0,0 +1,97 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.scripts; + +import java.util.ArrayList; +import java.util.List; + +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Script which creates the target version of the script through the class name. + *

+ * Class name has to be in the scheme:
+ * + * vM_Classname
vM_m_Classname
vM_m_m_Classname
+ *
+ * Where v is short for version and is a constant (just a char),
+ * M is a integer for the major version,
+ * m is a integer for the minor version
+ * Classname is a custom String that the user can choose.
+ * This scheme can basically be extended infinetly. For example: v1_1_2_2_MyUpdateScript + *

+ * Therefore the character _ can only be used as a seperator of versions and may not be used for other + * purposes. + *

+ * If the class name has the wrong format, an {@link Error} is thrown. + */ +public abstract class ReflectiveVersionMigrationScript< + T, + E extends VersionAgnosticMigrationEmbeddedStorageManager> + implements VersionAgnosticMigrationScript +{ + private static final char PREFIX = 'v'; + private static final String VERSION_SEPERATOR = "_"; + private static final String WRONG_FORMAT_ERROR_MESSAGE = + "Script has invalid class name. Either rename the class to a valid script class name, or implement method " + + "getTargetVersion()."; + + private final MigrationVersion version; + + /** + * @throws Error if the class name has the wrong format + */ + protected ReflectiveVersionMigrationScript() + { + this.version = this.createTargetVersionFromClassName(); + } + + private MigrationVersion createTargetVersionFromClassName() + { + final String implementationClassName = this.getClass().getSimpleName(); + if(PREFIX != implementationClassName.charAt(0)) + { + throw new IllegalArgumentException(WRONG_FORMAT_ERROR_MESSAGE); + } + final String implementationClassNameWithoutPrefix = implementationClassName.substring(1); + final String[] classNameParts = implementationClassNameWithoutPrefix.split(VERSION_SEPERATOR); + if(classNameParts.length < 2) + { + throw new IllegalArgumentException(WRONG_FORMAT_ERROR_MESSAGE); + } + try + { + final List versionNumbers = new ArrayList<>(); + for(int i = 0; i < classNameParts.length - 1; i++) + { + versionNumbers.add(Integer.parseInt(classNameParts[i])); + } + return new MigrationVersion(versionNumbers); + } + catch(final NumberFormatException e) + { + throw new IllegalArgumentException(WRONG_FORMAT_ERROR_MESSAGE, e); + } + } + + @Override + public MigrationVersion getTargetVersion() + { + return this.version; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/scripts/SimpleMigrationScript.java b/micro-migration/src/main/java/software/xdev/micromigration/scripts/SimpleMigrationScript.java new file mode 100644 index 0000000..fee2487 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/scripts/SimpleMigrationScript.java @@ -0,0 +1,41 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.scripts; + +import java.util.function.Consumer; + +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Provides a simple way to create a migration script with the necessary version and {@link Consumer}. + */ +public class SimpleMigrationScript> + extends SimpleTypedMigrationScript +{ + /** + * @param targetVersion to which the script is updating the object + * @param consumer which consumes the object and updates it to the target version + */ + public SimpleMigrationScript( + final MigrationVersion targetVersion, + final Consumer> consumer + ) + { + super(targetVersion, consumer); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/scripts/SimpleTypedMigrationScript.java b/micro-migration/src/main/java/software/xdev/micromigration/scripts/SimpleTypedMigrationScript.java new file mode 100644 index 0000000..1394f8b --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/scripts/SimpleTypedMigrationScript.java @@ -0,0 +1,60 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.scripts; + +import java.util.Objects; +import java.util.function.Consumer; + +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Provides a simple way to create a migration script with the necessary version and {@link Consumer}. + */ +public class SimpleTypedMigrationScript> + implements VersionAgnosticMigrationScript +{ + private final MigrationVersion version; + private final Consumer> consumer; + + /** + * @param version of the datastore after this script is executed + * @param consumer which is executed to reach the given datastore version + */ + public SimpleTypedMigrationScript( + final MigrationVersion version, + final Consumer> consumer + ) + { + Objects.requireNonNull(version); + Objects.requireNonNull(consumer); + this.version = version; + this.consumer = consumer; + } + + @Override + public MigrationVersion getTargetVersion() + { + return this.version; + } + + @Override + public void migrate(final Context context) + { + this.consumer.accept(context); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/scripts/VersionAgnosticMigrationScript.java b/micro-migration/src/main/java/software/xdev/micromigration/scripts/VersionAgnosticMigrationScript.java new file mode 100644 index 0000000..1e455c5 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/scripts/VersionAgnosticMigrationScript.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.scripts; + +import java.util.Comparator; + +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +/** + * Interface for scripts to migrate / update datastores. + *

+ * One script is supposed to bring a datastore from a lower version to the target version. After the + * {@link VersionAgnosticMigrationScript#migrate(Context)} method is called, the target version is reached. + */ +public interface VersionAgnosticMigrationScript> +{ + /** + * @return the version of the datastore after this script is executed. + */ + MigrationVersion getTargetVersion(); + + /** + * Execute logic to migrate the given datastore to a newer version of the store. After executing the + * {@link #getTargetVersion()} is reached. + * + * @param context that holds necessary data for the migration + */ + void migrate(Context context); + + /** + * Provides a {@link Comparator} that compares the {@link #getTargetVersion()} of the given scripts + */ + Comparator> COMPARATOR = + (o1, o2) -> MigrationVersion.COMPARATOR.compare(o1.getTargetVersion(), o2.getTargetVersion()); +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/MigrationVersion.java b/micro-migration/src/main/java/software/xdev/micromigration/version/MigrationVersion.java new file mode 100644 index 0000000..c5c9bae --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/MigrationVersion.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + + +/** + * Defines one version of the EclipseStore datastore. + */ +public class MigrationVersion +{ + private final int[] versions; + + /** + * @param versions as integers. For example 1.0.2 would be an array of [1,0,2] + */ + public MigrationVersion(final int... versions) + { + if(versions == null || versions.length == 0) + { + this.versions = new int[]{0}; + } + else + { + this.versions = versions; + } + } + + /** + * @param versionsAsList as integers. For example 1.0.2 would be a list of [1,0,2] + */ + public MigrationVersion(final List versionsAsList) + { + if(versionsAsList == null || versionsAsList.isEmpty()) + { + this.versions = new int[]{0}; + } + else + { + final int[] versionsAsArray = new int[versionsAsList.size()]; + for(int i = 0; i < versionsAsArray.length; i++) + { + versionsAsArray[i] = versionsAsList.get(i); + } + this.versions = versionsAsArray; + } + } + + /** + * @return versions as an array of integers. For example 1.0.2 would be an array of [1,0,2] + */ + public int[] getVersions() + { + return this.versions; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder("v"); + for(final int version : this.versions) + { + sb.append(version).append('.'); + } + sb.deleteCharAt(sb.length() - 1); + return sb.toString(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(this.versions); + return result; + } + + @Override + public boolean equals(final Object obj) + { + if(this == obj) + { + return true; + } + if(obj == null) + { + return false; + } + if(this.getClass() != obj.getClass()) + { + return false; + } + final MigrationVersion other = (MigrationVersion)obj; + return Arrays.equals(this.versions, other.versions); + } + + /** + * Provides a {@link Comparator} that compares the {@link #getVersions()} of the given versions + */ + public static final Comparator COMPARATOR = + Comparator.comparing(MigrationVersion::getVersions, Arrays::compare); +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/Versioned.java b/micro-migration/src/main/java/software/xdev/micromigration/version/Versioned.java new file mode 100644 index 0000000..80436da --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/Versioned.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +/** + * Interface used by the MigrationManagers for easier versioning of objects. + */ +public interface Versioned +{ + /** + * @param version to set the current version of the object + */ + void setVersion(MigrationVersion version); + + /** + * @return the current version of the object + */ + MigrationVersion getVersion(); +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedAndKeeperOfHistory.java b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedAndKeeperOfHistory.java new file mode 100644 index 0000000..37e85da --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedAndKeeperOfHistory.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import java.util.List; + +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithoutScriptReference; + +/** + * Interface used by the MigrationManagers for easier versioning of objects + * and to keep and read the migration history. + */ +public interface VersionedAndKeeperOfHistory extends Versioned +{ + /** + * Adds the information about the executed script to the history book. + * @param executedScriptInformation information about the executed script + */ + void addExecutedScript(ScriptExecutionNotificationWithoutScriptReference executedScriptInformation); + + /** + * @return the complete migration history. That means information about every executed script. + */ + List getMigrationHistory(); +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedObject.java b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedObject.java new file mode 100644 index 0000000..fe6e420 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedObject.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import java.util.Objects; + + +/** + * Simple container to hold a specific object and a correlating version for it. + * + * @param type of the object that's contained + */ +public class VersionedObject implements Versioned +{ + private MigrationVersion currentVersion; + private T actualObject; + + /** + * @param actualObject set the actual object which is versioned + */ + public VersionedObject(final T actualObject) + { + this.actualObject = actualObject; + this.currentVersion = new MigrationVersion(0); + } + + @Override + public void setVersion(final MigrationVersion version) + { + Objects.requireNonNull(version); + this.currentVersion = version; + } + + @Override + public MigrationVersion getVersion() + { + return this.currentVersion; + } + + /** + * @param actualObject which is versioned + */ + public void setObject(final T actualObject) + { + this.actualObject = actualObject; + } + + /** + * @return the actual object which is versioned + */ + public T getObject() + { + return this.actualObject; + } + + @Override + public String toString() + { + return this.currentVersion.toString() + "\n" + this.actualObject; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedObjectWithHistory.java b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedObjectWithHistory.java new file mode 100644 index 0000000..08e0360 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedObjectWithHistory.java @@ -0,0 +1,53 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithoutScriptReference; + + +/** + * This class is inserted as the root of the datastore and contains only the current version, the actual + * root object and the history of executed scripts. + */ +public class VersionedObjectWithHistory extends VersionedObject implements VersionedAndKeeperOfHistory +{ + private final List migrationHistory; + + /** + * @param actualRoot which is stored in the datastore and defined by the user + */ + public VersionedObjectWithHistory(final Object actualRoot) + { + super(actualRoot); + this.migrationHistory = new ArrayList<>(); + } + + @Override + public void addExecutedScript(final ScriptExecutionNotificationWithoutScriptReference executedScriptInformation) + { + this.migrationHistory.add(Objects.requireNonNull(executedScriptInformation)); + } + + @Override + public List getMigrationHistory() + { + return this.migrationHistory; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedRoot.java b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedRoot.java new file mode 100644 index 0000000..48f54c8 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedRoot.java @@ -0,0 +1,67 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import java.util.Objects; + + +/** + * This class is inserted as the root of the datastore and contains only the current version and the actual root + * object. + */ +public class VersionedRoot implements Versioned +{ + private MigrationVersion currentVersion; + private Object actualRoot; + + /** + * @param actualRoot which is stored in the datastore and defined by the user + */ + public VersionedRoot(final Object actualRoot) + { + this.actualRoot = actualRoot; + this.currentVersion = new MigrationVersion(0); + } + + @Override + public void setVersion(final MigrationVersion version) + { + Objects.requireNonNull(version); + this.currentVersion = version; + } + + @Override + public MigrationVersion getVersion() + { + return this.currentVersion; + } + + /** + * @param actualRoot which is stored in the datastore and defined by the user + */ + public void setRoot(final Object actualRoot) + { + this.actualRoot = actualRoot; + } + + /** + * @return the actual root, that's defined by the user + */ + public Object getRoot() + { + return this.actualRoot; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedRootWithHistory.java b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedRootWithHistory.java new file mode 100644 index 0000000..bdbfc58 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/version/VersionedRootWithHistory.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithoutScriptReference; + + +/** + * This class is inserted as the root of the datastore and contains only the current version, the actual root object + * and the history of executed scripts. + */ +public class VersionedRootWithHistory extends VersionedRoot implements VersionedAndKeeperOfHistory +{ + private final List migrationHistory; + + /** + * @param actualRoot which is stored in the datastore and defined by the user + */ + public VersionedRootWithHistory(final Object actualRoot) + { + super(actualRoot); + this.migrationHistory = new ArrayList<>(); + } + + @Override + public void addExecutedScript(final ScriptExecutionNotificationWithoutScriptReference executedScriptInformation) + { + this.migrationHistory.add(Objects.requireNonNull(executedScriptInformation)); + } + + /** + * @return the complete migration history. That means information about every executed script. + */ + @Override + public List getMigrationHistory() + { + return this.migrationHistory; + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticMigrationEmbeddedStorageManager.java b/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticMigrationEmbeddedStorageManager.java new file mode 100644 index 0000000..a3a58f0 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticMigrationEmbeddedStorageManager.java @@ -0,0 +1,188 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.versionagnostic; + +import java.util.List; +import java.util.Objects; + +import software.xdev.micromigration.migrater.MicroMigrater; +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithoutScriptReference; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.version.Versioned; +import software.xdev.micromigration.version.VersionedRoot; +import software.xdev.micromigration.version.VersionedRootWithHistory; + + +/** + * Wrapper class for the {@link org.eclipse.store.storage.embedded.types.EmbeddedStorageManager} interface. + *

+ * Basically it intercepts storing the root object and places a {@link Versioned} in front of it. This means the root + * object of the datastore is then versioned.
Internally uses the {@link VersionAgnosticMigrationManager} to do the + * actual migration. + *

+ * {@code VersionAgnostic} because it should be independent of the actual implementation used. + * + * @param class of itself to be able to return the actual class and not just a generic class + * @param The actually used EmbeddedStorageManager + */ +public abstract class VersionAgnosticMigrationEmbeddedStorageManager + implements AutoCloseable +{ + private final MicroMigrater migrater; + private VersionedRootWithHistory versionRoot; + private final VersionAgnosticTunnelingEmbeddedStorageManager tunnelingManager; + + /** + * @param tunnelingManager which will be used as the underlying storage manager. Almost all methods are only + * rerouted to this native manager. Only {@link #start()}, {@link #root()} and + * {@link #setRoot(Object)} are intercepted and a {@link Versioned} is placed between the + * requests. + * @param migrater which is used as source for the migration scripts + */ + protected VersionAgnosticMigrationEmbeddedStorageManager( + final VersionAgnosticTunnelingEmbeddedStorageManager tunnelingManager, + final MicroMigrater migrater + ) + { + this.tunnelingManager = Objects.requireNonNull(tunnelingManager); + this.migrater = Objects.requireNonNull(migrater); + } + + /** + * @return the native EmbeddedStorageManager + */ + public E getNativeStorageManager() + { + return this.getTunnelingManager().getNativeStorageManager(); + } + + /** + * @return the used {@link VersionAgnosticTunnelingEmbeddedStorageManager} + */ + protected VersionAgnosticTunnelingEmbeddedStorageManager getTunnelingManager() + { + return this.tunnelingManager; + } + + /** + * Checks if the root object is of the instance of {@link Versioned}. If it is not, the root will be replaced with + * the versioned root and the actual root object will be put inside the versioned root. + *

+ * After starting the storage manager, all the available update scripts are executed in order until the newest + * version of the datastore is reached. + * + * @return itself + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public T start() + { + this.tunnelingManager.start(); + if(this.tunnelingManager.root() instanceof final VersionedRootWithHistory versionedRootWithHistory) + { + this.versionRoot = versionedRootWithHistory; + } + else + { + // Build VersionedRootWithHistory around actual root, set by user. + this.versionRoot = new VersionedRootWithHistory(this.tunnelingManager.root()); + this.tunnelingManager.setRoot(this.versionRoot); + this.tunnelingManager.storeRoot(); + } + new VersionAgnosticMigrationManager( + this.versionRoot, + this.migrater, + this + ).migrate(this.versionRoot.getRoot()); + return (T)this; + } + + /** + * @return current version that's managed + */ + public MigrationVersion getCurrentVersion() + { + return this.versionRoot.getVersion(); + } + + /** + * @return the actual root object + */ + public Object root() + { + return this.versionRoot.getRoot(); + } + + /** + * @return the actual root object + */ + public List getMigrationHistory() + { + return this.versionRoot.getMigrationHistory(); + } + + /** + * Sets the actual root element (not the versioned root) + * + * @param newRoot to set + * @return the set object + */ + public Object setRoot(final Object newRoot) + { + this.versionRoot.setRoot(newRoot); + return newRoot; + } + + /** + * Stores the {@link VersionedRoot} and the actual root object. + * + * @return what EmbeddedStorageManager#storeRoot returns + */ + public long storeRoot() + { + this.tunnelingManager.store(this.versionRoot); + return this.tunnelingManager.store(this.versionRoot.getRoot()); + } + + /** + * Stores the objectToStore + * + * @param objectToStore which is stored + * @return what EmbeddedStorageManager#store returns + */ + public long store(final Object objectToStore) + { + return this.tunnelingManager.store(objectToStore); + } + + /** + * Shuts down the datastore. + * + * @return what EmbeddedStorageManager#storeRoot shutdown + */ + public boolean shutdown() + { + return this.tunnelingManager.shutdown(); + } + + /** + * Closes the datastore. + */ + @Override + public void close() + { + this.tunnelingManager.close(); + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticMigrationManager.java b/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticMigrationManager.java new file mode 100644 index 0000000..b655376 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticMigrationManager.java @@ -0,0 +1,163 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.versionagnostic; + +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import software.xdev.micromigration.migrater.MicroMigrater; +import software.xdev.micromigration.notification.ScriptExecutionNotificationWithoutScriptReference; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.version.Versioned; +import software.xdev.micromigration.version.VersionedAndKeeperOfHistory; + + +/** + * Manages a given object and keeps the version for it. + *

+ * Can be used to keep the version of the Root-Object and therefor keep the whole datastore versioned. + *

+ *

+ * {@code VersionAgnostic} because it should be independent of the actual implementation used. + *

+ * + * @param The actually used EmbeddedStorageManager + */ +public class VersionAgnosticMigrationManager +{ + private final Supplier currentVersionGetter; + private final Consumer currentVersionSetter; + private final Consumer currentVersionStorer; + private final MicroMigrater migrater; + private final VersionAgnosticMigrationEmbeddedStorageManager storageManager; + + /** + * Much more complicated constructor than + * {@link VersionAgnosticMigrationManager#VersionAgnosticMigrationManager(Versioned, MicroMigrater, + * VersionAgnosticMigrationEmbeddedStorageManager)} + * + * @param currentVersionGetter which supplies the current version of the object to update. + * @param currentVersionSetter which sets the new version of the object in some membervariable. This Consumer is + * not + * supposed to store the version, but only save it in some membervariable to be stored + * after. + * @param currentVersionStorer which is supposed to store the new version of the object somewhere in the datastore. + * @param migrater does the actual migration with the given {@link VersionAgnosticMigrationScript} + * @param storageManager for the {@link VersionAgnosticMigrationScript}s to use. Is not used for the storing + * of the new version. + */ + public VersionAgnosticMigrationManager( + final Supplier currentVersionGetter, + final Consumer currentVersionSetter, + final Consumer currentVersionStorer, + final MicroMigrater migrater, + final VersionAgnosticMigrationEmbeddedStorageManager storageManager + ) + { + Objects.requireNonNull(currentVersionGetter); + Objects.requireNonNull(currentVersionSetter); + Objects.requireNonNull(currentVersionStorer); + Objects.requireNonNull(migrater); + Objects.requireNonNull(storageManager); + this.currentVersionGetter = currentVersionGetter; + this.currentVersionSetter = currentVersionSetter; + this.currentVersionStorer = currentVersionStorer; + this.migrater = migrater; + this.storageManager = storageManager; + } + + /** + * Simple Constructor. + * + * @param versionedObject which provides getter and setter for the current version. This object will be stored + * after + * the {@link VersionAgnosticMigrationScript}s are executed. + * @param migrater does the actual migration with the given {@link VersionAgnosticMigrationScript} + * @param storageManager for the {@link VersionAgnosticMigrationScript}s to use. Is not used for the storing of + * the + * new version. + */ + public VersionAgnosticMigrationManager( + final Versioned versionedObject, + final MicroMigrater migrater, + final VersionAgnosticMigrationEmbeddedStorageManager storageManager + ) + { + this( + versionedObject::getVersion, + versionedObject::setVersion, + version -> storageManager.store(versionedObject), + migrater, + storageManager + ); + Objects.requireNonNull(versionedObject); + } + + /** + * Simple Constructor. + * + * @param versionedObject which provides getter and setter for the current version. This object will be stored + * after + * the {@link VersionAgnosticMigrationScript}s are executed. + * @param migrater does the actual migration with the given {@link VersionAgnosticMigrationScript} + * @param storageManager for the {@link VersionAgnosticMigrationScript}s to use. Is not used for the storing of + * the + * new version. + */ + public VersionAgnosticMigrationManager( + final VersionedAndKeeperOfHistory versionedObject, + final MicroMigrater migrater, + final VersionAgnosticMigrationEmbeddedStorageManager storageManager + ) + { + this( + versionedObject::getVersion, + versionedObject::setVersion, + version -> storageManager.store(versionedObject), + migrater, + storageManager + ); + Objects.requireNonNull(versionedObject); + migrater.registerNotificationConsumer( + executedScript -> + versionedObject.addExecutedScript(new ScriptExecutionNotificationWithoutScriptReference(executedScript)) + ); + } + + /** + * Migrates the given object to the newest possible version, defined by the {@link MicroMigrater}. + * + * @param objectToMigrate is given to the {@link MicroMigrater} for migrating upon + */ + public void migrate(final Object objectToMigrate) + { + final MigrationVersion versionBeforeUpdate = this.currentVersionGetter.get(); + // Execute Updates + final MigrationVersion versionAfterUpdate = this.migrater.migrateToNewest( + versionBeforeUpdate, + this.storageManager, + objectToMigrate + ); + // Update stored version, if needed + if(!versionAfterUpdate.equals(versionBeforeUpdate)) + { + this.currentVersionSetter.accept(versionAfterUpdate); + this.currentVersionStorer.accept(versionAfterUpdate); + } + } +} diff --git a/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticTunnelingEmbeddedStorageManager.java b/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticTunnelingEmbeddedStorageManager.java new file mode 100644 index 0000000..45e3c73 --- /dev/null +++ b/micro-migration/src/main/java/software/xdev/micromigration/versionagnostic/VersionAgnosticTunnelingEmbeddedStorageManager.java @@ -0,0 +1,156 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.versionagnostic; + +/** + * Wrapper class for the {@link org.eclipse.store.storage.embedded.types.EmbeddedStorageManager} interface. + *

+ * It's simply an interface to not directly depend on the underlying framework, but still use its functionality. + *

+ *

+ * {@code VersionAgnostic} because it should be independent of the actual implementation used. + *

+ * + * @param Represents the actually used EmbeddedStorageManager + */ +public interface VersionAgnosticTunnelingEmbeddedStorageManager + extends AutoCloseable +{ + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + T start(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + Object root(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @param newRoot whatever the actual EmbeddedStorageManager uses this for + * @return what the actual EmbeddedStorageManager returns + */ + Object setRoot(Object newRoot); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + long storeRoot(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + boolean shutdown(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + boolean isAcceptingTasks(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + boolean isRunning(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + boolean isStartingUp(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + boolean isShuttingDown(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + */ + void checkAcceptingTasks(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + long initializationTime(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + long operationModeTime(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @return what the actual EmbeddedStorageManager returns + */ + boolean isActive(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @param nanoTimeBudget whatever the actual EmbeddedStorageManager uses this for + * @return what the actual EmbeddedStorageManager returns + */ + boolean issueGarbageCollection(long nanoTimeBudget); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @param nanoTimeBudget whatever the actual EmbeddedStorageManager uses this for + * @return what the actual EmbeddedStorageManager returns + */ + boolean issueFileCheck(long nanoTimeBudget); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + * + * @param instance whatever the actual EmbeddedStorageManager uses this for + * @return what the actual EmbeddedStorageManager returns + */ + long store(Object instance); + + /** + * @return the actual EmbeddedStorageManager + */ + T getNativeStorageManager(); + + /** + * Simply relais the method-call to the EmbeddedStorageManager + */ + @Override + void close(); +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/IntroduceMigrationOnExistingDatastoreTest.java b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/IntroduceMigrationOnExistingDatastoreTest.java new file mode 100644 index 0000000..7668cb9 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/IntroduceMigrationOnExistingDatastoreTest.java @@ -0,0 +1,58 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore.integration; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.nio.file.Path; + +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.util.MicroMigrationScriptDummy; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.version.MigrationVersion; + + +class IntroduceMigrationOnExistingDatastoreTest +{ + static final String ROOT = "OriginalRoot"; + + @Test + void checkIntroducingMigrationOnExistingDatastoreMigrationEmbeddedStorageManager(@TempDir final Path storageFolder) + { + try(final EmbeddedStorageManager storageManager = EmbeddedStorage.start(storageFolder)) + { + storageManager.setRoot(ROOT); + storageManager.storeRoot(); + } + + final ExplicitMigrater migrater = new ExplicitMigrater( + new MicroMigrationScriptDummy(new MigrationVersion(1)) + ); + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + migrater)) + { + assertEquals(ROOT, migrationStorageManager.root()); + assertEquals(1, migrationStorageManager.getCurrentVersion().getVersions()[0]); + } + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/MigrationScriptAfterScriptTest.java b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/MigrationScriptAfterScriptTest.java new file mode 100644 index 0000000..0f18f5c --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/MigrationScriptAfterScriptTest.java @@ -0,0 +1,202 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore.integration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.serializer.persistence.types.Storer; +import org.eclipse.store.storage.embedded.types.EmbeddedStorage; +import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.MigrationManager; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.scripts.SimpleTypedMigrationScript; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.version.Versioned; +import software.xdev.micromigration.version.VersionedObject; + + +class MigrationScriptAfterScriptTest +{ + @Test + void checkMigrationWithThreeDifferentMigraterMigrationEmbeddedStorageManager(@TempDir final Path storageFolder) + { + // First run without any migration script + final ExplicitMigrater firstMigrater = new ExplicitMigrater(); + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + firstMigrater)) + { + migrationStorageManager.setRoot(0); + migrationStorageManager.storeRoot(); + assertEquals(0, migrationStorageManager.root()); + Assertions.assertEquals(new MigrationVersion(0), migrationStorageManager.getCurrentVersion()); + } + + // Run with one migration script + final VersionAgnosticMigrationScript firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(1) + ); + final ExplicitMigrater secondMigrater = new ExplicitMigrater(firstScript); + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + secondMigrater)) + { + assertEquals(1, migrationStorageManager.root()); + Assertions.assertEquals(new MigrationVersion(1), migrationStorageManager.getCurrentVersion()); + } + + // Run with two migration scripts + final VersionAgnosticMigrationScript secondScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(2), + (context) -> context.getStorageManager().setRoot(2) + ); + final ExplicitMigrater thirdMigrater = new ExplicitMigrater(firstScript, secondScript); + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + thirdMigrater)) + { + assertEquals(2, migrationStorageManager.root()); + Assertions.assertEquals(new MigrationVersion(2), migrationStorageManager.getCurrentVersion()); + } + } + + @Test + void checkMigrationAndUseStorer(@TempDir final Path storageFolder) + { + final List firstList = new ArrayList<>(); + // Run with one migration script + final VersionAgnosticMigrationScript firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> + { + context.getStorageManager().setRoot(firstList); + firstList.add("1"); + final Storer storer = context.getStorageManager().getNativeStorageManager().createStorer(); + storer.store(firstList); + storer.commit(); + } + ); + + final ExplicitMigrater migrater = new ExplicitMigrater(firstScript); + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + migrater)) + { + assertEquals(1, ((List)migrationStorageManager.root()).size()); + } + } + + @Test + void checkMigrationWithScriptExecutionNotification(@TempDir final Path storageFolder) + { + final VersionAgnosticMigrationScript firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(1) + ); + final ExplicitMigrater migrater = new ExplicitMigrater(firstScript); + final AtomicBoolean notificationReceived = new AtomicBoolean(false); + migrater.registerNotificationConsumer( + notification -> + { + Assertions.assertEquals(firstScript, notification.getExecutedScript()); + Assertions.assertEquals(new MigrationVersion(0), notification.getSourceVersion()); + Assertions.assertEquals(new MigrationVersion(1), notification.getTargetVersion()); + notificationReceived.set(true); + } + ); + try(final MigrationEmbeddedStorageManager ignored = MigrationEmbeddedStorage.start(storageFolder, migrater)) + { + assertTrue(notificationReceived.get()); + } + } + + @Test + void checkMigrationWithThreeDifferentMigraterStandaloneMicroMigrationManager(@TempDir final Path storageFolder) + { + // First run without any migration script + try(final EmbeddedStorageManager storageManager = this.startEmbeddedStorageManagerWithPath(storageFolder)) + { + final VersionedObject firstRoot = new VersionedObject<>(0); + storageManager.setRoot(firstRoot); + storageManager.storeRoot(); + assertEquals(Integer.valueOf(0), firstRoot.getObject()); + assertEquals(new MigrationVersion(0), firstRoot.getVersion()); + } + + // Run with one migration script + final VersionAgnosticMigrationScript, MigrationEmbeddedStorageManager> firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getMigratingObject().setObject(1) + ); + try(final EmbeddedStorageManager storageManager = this.startEmbeddedStorageManagerWithPath(storageFolder)) + { + new MigrationManager( + (Versioned)storageManager.root(), + new ExplicitMigrater(firstScript), + storageManager + ) + .migrate(storageManager.root()); + @SuppressWarnings("unchecked") + final VersionedObject currentRoot = (VersionedObject)storageManager.root(); + assertEquals(Integer.valueOf(1), currentRoot.getObject()); + assertEquals(new MigrationVersion(1), currentRoot.getVersion()); + } + + // Run with two migration scripts + final VersionAgnosticMigrationScript, MigrationEmbeddedStorageManager> secondScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(2), + (context) -> context.getMigratingObject().setObject(2) + ); + try(final EmbeddedStorageManager storageManager = this.startEmbeddedStorageManagerWithPath(storageFolder)) + { + new MigrationManager( + (Versioned)storageManager.root(), + new ExplicitMigrater(firstScript, secondScript), + storageManager + ) + .migrate(storageManager.root()); + @SuppressWarnings("unchecked") + final VersionedObject currentRoot = (VersionedObject)storageManager.root(); + assertEquals(Integer.valueOf(2), currentRoot.getObject()); + assertEquals(new MigrationVersion(2), currentRoot.getVersion()); + } + } + + private EmbeddedStorageManager startEmbeddedStorageManagerWithPath(final Path storageFolder) + { + return EmbeddedStorage.start(storageFolder); + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/MultipleScriptsTest.java b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/MultipleScriptsTest.java new file mode 100644 index 0000000..458e1fd --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/MultipleScriptsTest.java @@ -0,0 +1,100 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore.integration; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.migrater.VersionAlreadyRegisteredException; +import software.xdev.micromigration.scripts.SimpleTypedMigrationScript; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +class MultipleScriptsTest +{ + @Test + void checkMigrationWithTwoScriptsAtOnceMigrationEmbeddedStorageManager(@TempDir final Path storageFolder) + { + final VersionAgnosticMigrationScript firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(1) + ); + final VersionAgnosticMigrationScript secondScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(2), + (context) -> context.getStorageManager().setRoot(2) + ); + final ExplicitMigrater migrater = new ExplicitMigrater(firstScript, secondScript); + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + migrater)) + { + assertEquals(2, migrationStorageManager.root()); + assertEquals(new MigrationVersion(2), migrationStorageManager.getCurrentVersion()); + } + } + + @Test + void checkMigrationWithTwoScriptsWithSameVersion() + { + final VersionAgnosticMigrationScript firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(1) + ); + final VersionAgnosticMigrationScript secondScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(2) + ); + Assertions.assertThrows(VersionAlreadyRegisteredException.class, () -> + new ExplicitMigrater(firstScript, secondScript) + ); + } + + @Test + void checkMigrationWithThreeScriptsWithSameVersion() + { + final VersionAgnosticMigrationScript firstScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(1) + ); + final VersionAgnosticMigrationScript secondScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(2), + (context) -> context.getStorageManager().setRoot(2) + ); + final VersionAgnosticMigrationScript thirdScript = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(3) + ); + Assertions.assertThrows(VersionAlreadyRegisteredException.class, () -> + new ExplicitMigrater(firstScript, secondScript, thirdScript) + ); + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/StoreStuffInMigrationStorageManagerTest.java b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/StoreStuffInMigrationStorageManagerTest.java new file mode 100644 index 0000000..19fa22c --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/integration/StoreStuffInMigrationStorageManagerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore.integration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.scripts.SimpleTypedMigrationScript; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +class StoreStuffInMigrationStorageManagerTest +{ + static class RootClass + { + private final ChildClass child = new ChildClass(); + } + + + static class ChildClass + { + private int i; + } + + @Test + void checkStoringSomethingAfterUpdating(@TempDir final Path storageFolder) + { + final VersionAgnosticMigrationScript script = + new SimpleTypedMigrationScript<>( + new MigrationVersion(1), + (context) -> { + } + ); + final ExplicitMigrater migrater = new ExplicitMigrater(script); + // Create new store and change stored object + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + migrater)) + { + migrationStorageManager.setRoot(new RootClass()); + migrationStorageManager.storeRoot(); + final RootClass storedRoot = ((RootClass)migrationStorageManager.root()); + assertEquals(0, storedRoot.child.i); + ((RootClass)migrationStorageManager.root()).child.i = 1; + migrationStorageManager.store(storedRoot.child); + assertEquals(1, storedRoot.child.i); + } + // Check if stored object is correct + try(final MigrationEmbeddedStorageManager migrationStorageManager = MigrationEmbeddedStorage.start( + storageFolder, + migrater)) + { + final RootClass storedRoot = ((RootClass)migrationStorageManager.root()); + assertNotNull(storedRoot); + assertEquals(1, storedRoot.child.i); + } + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/migrater/ExplicitMigraterTest.java b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/migrater/ExplicitMigraterTest.java new file mode 100644 index 0000000..3db6830 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/migrater/ExplicitMigraterTest.java @@ -0,0 +1,86 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore.migrater; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.nio.file.Path; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorage; +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.eclipsestore.util.MicroMigrationScriptDummy; +import software.xdev.micromigration.migrater.ExplicitMigrater; +import software.xdev.micromigration.scripts.SimpleTypedMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +class ExplicitMigraterTest +{ + + @Test + void checkGetSortedScriptsEmpty() + { + final ExplicitMigrater migrater = new ExplicitMigrater(); + assertEquals(0, migrater.getSortedScripts().size()); + } + + @Test + void checkGetSortedScriptsSorted() + { + final ExplicitMigrater migrater = new ExplicitMigrater( + new MicroMigrationScriptDummy(new MigrationVersion(1)), + new MicroMigrationScriptDummy(new MigrationVersion(2)) + ); + assertEquals(1, migrater.getSortedScripts().first().getTargetVersion().getVersions()[0]); + assertEquals(2, migrater.getSortedScripts().last().getTargetVersion().getVersions()[0]); + } + + @Test + void checkGetSortedScriptsUnsorted() + { + final ExplicitMigrater migrater = new ExplicitMigrater( + new MicroMigrationScriptDummy(new MigrationVersion(2)), + new MicroMigrationScriptDummy(new MigrationVersion(1)) + ); + assertEquals(1, migrater.getSortedScripts().first().getTargetVersion().getVersions()[0]); + assertEquals(2, migrater.getSortedScripts().last().getTargetVersion().getVersions()[0]); + } + + @Test + void checkWrongTypedVersionedScript(@TempDir final Path storageFolder) + { + try(final MigrationEmbeddedStorageManager storageManager = MigrationEmbeddedStorage.start( + storageFolder, + new ExplicitMigrater())) + { + storageManager.setRoot("SomeString"); + storageManager.storeRoot(); + } + final ExplicitMigrater migrater = new ExplicitMigrater( + new SimpleTypedMigrationScript( + new MigrationVersion(1), + (context) -> context.getStorageManager().setRoot(context.getMigratingObject() + 1) + ) + ); + Assertions.assertThrows( + ClassCastException.class, + () -> MigrationEmbeddedStorage.start(storageFolder, migrater)); + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/util/MicroMigrationScriptDummy.java b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/util/MicroMigrationScriptDummy.java new file mode 100644 index 0000000..2b913c6 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/eclipsestore/util/MicroMigrationScriptDummy.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.eclipsestore.util; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class MicroMigrationScriptDummy + implements VersionAgnosticMigrationScript +{ + private final MigrationVersion version; + + public MicroMigrationScriptDummy(final MigrationVersion version) + { + this.version = version; + } + + @Override + public MigrationVersion getTargetVersion() + { + return this.version; + } + + @Override + public void migrate(final Context context) + { + // Don't do anything. + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/ReflectiveMigraterTest.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/ReflectiveMigraterTest.java new file mode 100644 index 0000000..88ac538 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/ReflectiveMigraterTest.java @@ -0,0 +1,138 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import software.xdev.micromigration.migrater.reflection.scripts.abstractReflectiveSuperClass.v1_ValidScript; + + +class ReflectiveMigraterTest +{ + @Test + void testValidScript() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.valid"); + assertEquals(1, migrater.getSortedScripts().size()); + assertEquals( + software.xdev.micromigration.migrater.reflection.scripts.valid.ValidScript.class, + migrater.getSortedScripts().first().getClass() + ); + } + + @Test + void testValidScriptWithIrrelevantClasses() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts" + + ".moreClassesIncludingValid"); + assertEquals(1, migrater.getSortedScripts().size()); + assertEquals( + software.xdev.micromigration.migrater.reflection.scripts.moreClassesIncludingValid.ValidScript.class, + migrater.getSortedScripts().first().getClass() + ); + } + + @Test + void testValidScriptWithSubpackages() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.includeSubPackages"); + assertEquals(2, migrater.getSortedScripts().size()); + assertEquals( + software.xdev.micromigration.migrater.reflection.scripts.includeSubPackages.ValidScript.class, + migrater.getSortedScripts().first().getClass() + ); + assertEquals( + software.xdev.micromigration.migrater.reflection.scripts.includeSubPackages.subpackage + .ValidScriptInSubpackage.class, + migrater.getSortedScripts().last().getClass() + ); + } + + @Test + void testPackageWithNoScript() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.packageNotExisting"); + assertEquals(0, migrater.getSortedScripts().size()); + } + + @Test + void testExceptionThrowingScript() + { + Assertions.assertThrows(ScriptInstantiationException.class, () -> { + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.exceptionThrowing"); + }); + } + + @Test + void testErrorThrowingScript() + { + Assertions.assertThrows(ScriptInstantiationException.class, () -> { + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.errorThrowing"); + }); + } + + @Test + void testNoCorrectConstructor() + { + Assertions.assertThrows(ScriptInstantiationException.class, () -> { + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.noCorrectConstructor"); + }); + } + + @Test + void testAbstractSuperClass() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.abstractSuperClass"); + assertEquals(1, migrater.getSortedScripts().size()); + assertEquals( + software.xdev.micromigration.migrater.reflection.scripts.abstractSuperClass.ValidScript.class, + migrater.getSortedScripts().first().getClass() + ); + } + + @Test + void testReflectiveVersion() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater("software.xdev.micromigration.migrater.reflection.scripts.reflectiveVersion"); + assertEquals(1, migrater.getSortedScripts().size()); + assertEquals( + software.xdev.micromigration.migrater.reflection.scripts.reflectiveVersion.v1_ValidScript.class, + migrater.getSortedScripts().first().getClass() + ); + } + + @Test + void testReflectiveSuperClass() + { + final ReflectiveMigrater migrater = + new ReflectiveMigrater( + "software.xdev.micromigration.migrater.reflection.scripts.abstractReflectiveSuperClass"); + assertEquals(1, migrater.getSortedScripts().size()); + assertEquals( + v1_ValidScript.class, + migrater.getSortedScripts().first().getClass() + ); + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractReflectiveSuperClass/AbstractScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractReflectiveSuperClass/AbstractScript.java new file mode 100644 index 0000000..f7b1b4c --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractReflectiveSuperClass/AbstractScript.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.abstractReflectiveSuperClass; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.ReflectiveVersionMigrationScript; + + +public abstract class AbstractScript extends ReflectiveVersionMigrationScript +{ + +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractReflectiveSuperClass/v1_ValidScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractReflectiveSuperClass/v1_ValidScript.java new file mode 100644 index 0000000..a9b2dda --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractReflectiveSuperClass/v1_ValidScript.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.abstractReflectiveSuperClass; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; + + +@SuppressWarnings("checkstyle:TypeName") +public class v1_ValidScript extends AbstractScript +{ + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractSuperClass/AbstractScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractSuperClass/AbstractScript.java new file mode 100644 index 0000000..92d310b --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractSuperClass/AbstractScript.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.abstractSuperClass; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public abstract class AbstractScript implements VersionAgnosticMigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractSuperClass/ValidScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractSuperClass/ValidScript.java new file mode 100644 index 0000000..55ae044 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/abstractSuperClass/ValidScript.java @@ -0,0 +1,29 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.abstractSuperClass; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; + + +public class ValidScript extends AbstractScript +{ + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/errorThrowing/ErrorThrowingScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/errorThrowing/ErrorThrowingScript.java new file mode 100644 index 0000000..e0de160 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/errorThrowing/ErrorThrowingScript.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.errorThrowing; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class ErrorThrowingScript implements VersionAgnosticMigrationScript +{ + public ErrorThrowingScript() + { + throw new Error(); + } + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } + + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/exceptionThrowing/ExceptionThrowingScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/exceptionThrowing/ExceptionThrowingScript.java new file mode 100644 index 0000000..1b3bb1e --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/exceptionThrowing/ExceptionThrowingScript.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.exceptionThrowing; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class ExceptionThrowingScript implements VersionAgnosticMigrationScript +{ + public ExceptionThrowingScript() throws Exception + { + throw new Exception(); + } + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } + + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/includeSubPackages/ValidScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/includeSubPackages/ValidScript.java new file mode 100644 index 0000000..e11bfd8 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/includeSubPackages/ValidScript.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.includeSubPackages; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class ValidScript implements VersionAgnosticMigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } + + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/includeSubPackages/subpackage/ValidScriptInSubpackage.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/includeSubPackages/subpackage/ValidScriptInSubpackage.java new file mode 100644 index 0000000..336101d --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/includeSubPackages/subpackage/ValidScriptInSubpackage.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.includeSubPackages.subpackage; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class ValidScriptInSubpackage implements VersionAgnosticMigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(2); + } + + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/moreClassesIncludingValid/IrrelevantClass.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/moreClassesIncludingValid/IrrelevantClass.java new file mode 100644 index 0000000..6b45813 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/moreClassesIncludingValid/IrrelevantClass.java @@ -0,0 +1,21 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.moreClassesIncludingValid; + +public class IrrelevantClass +{ + +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/moreClassesIncludingValid/ValidScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/moreClassesIncludingValid/ValidScript.java new file mode 100644 index 0000000..c67b8b6 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/moreClassesIncludingValid/ValidScript.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.moreClassesIncludingValid; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class ValidScript implements VersionAgnosticMigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } + + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/noCorrectConstructor/NoCorrectConstructorScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/noCorrectConstructor/NoCorrectConstructorScript.java new file mode 100644 index 0000000..a94408a --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/noCorrectConstructor/NoCorrectConstructorScript.java @@ -0,0 +1,47 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.noCorrectConstructor; + +import java.util.logging.Logger; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class NoCorrectConstructorScript + implements VersionAgnosticMigrationScript +{ + private final String argument; + + public NoCorrectConstructorScript(final String argument) + { + this.argument = argument; + } + + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } + + @Override + public void migrate(final Context context) + { + Logger.getGlobal().info(this.argument); + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/reflectiveVersion/v1_ValidScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/reflectiveVersion/v1_ValidScript.java new file mode 100644 index 0000000..8655a3d --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/reflectiveVersion/v1_ValidScript.java @@ -0,0 +1,31 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.reflectiveVersion; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.ReflectiveVersionMigrationScript; + + +@SuppressWarnings("checkstyle:TypeName") +public class v1_ValidScript extends ReflectiveVersionMigrationScript +{ + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/valid/ValidScript.java b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/valid/ValidScript.java new file mode 100644 index 0000000..3d1bb0a --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/migrater/reflection/scripts/valid/ValidScript.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.migrater.reflection.scripts.valid; + +import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager; +import software.xdev.micromigration.scripts.Context; +import software.xdev.micromigration.scripts.VersionAgnosticMigrationScript; +import software.xdev.micromigration.version.MigrationVersion; + + +public class ValidScript implements VersionAgnosticMigrationScript +{ + @Override + public MigrationVersion getTargetVersion() + { + return new MigrationVersion(1); + } + + @Override + public void migrate(final Context context) + { + // Do nothing + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/scripts/ReflectiveVersionMigrationScriptTest.java b/micro-migration/src/test/java/software/xdev/micromigration/scripts/ReflectiveVersionMigrationScriptTest.java new file mode 100644 index 0000000..de0b5b2 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/scripts/ReflectiveVersionMigrationScriptTest.java @@ -0,0 +1,179 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.scripts; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import software.xdev.micromigration.version.MigrationVersion; +import software.xdev.micromigration.versionagnostic.VersionAgnosticMigrationEmbeddedStorageManager; + + +@SuppressWarnings({"checkstyle:TypeName", "checkstyle:MethodName"}) +class ReflectiveVersionMigrationScriptTest +{ + public static class v1_CorrectClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void correctName_v1_CorrectClassName() + { + Assertions.assertEquals(new MigrationVersion(1), new v1_CorrectClassName().getTargetVersion()); + } + + public static class v1_1_CorrectClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void correctName_v1_1_CorrectClassName() + { + Assertions.assertEquals(new MigrationVersion(1, 1), new v1_1_CorrectClassName().getTargetVersion()); + } + + public static class v1_1_1_CorrectClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void correctName_v1_1_1_CorrectClassName() + { + Assertions.assertEquals(new MigrationVersion(1, 1, 1), new v1_1_1_CorrectClassName().getTargetVersion()); + } + + public static class v10_1_1_CorrectClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void correctName_v10_1_1_CorrectClassName() + { + Assertions.assertEquals(new MigrationVersion(10, 1, 1), new v10_1_1_CorrectClassName().getTargetVersion()); + } + + public static class v10_10_1_CorrectClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void correctName_v10_10_1_CorrectClassName() + { + Assertions.assertEquals(new MigrationVersion(10, 10, 1), new v10_10_1_CorrectClassName().getTargetVersion()); + } + + public static class v10_10_10_CorrectClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void correctName_v10_10_10_CorrectClassName() + { + Assertions.assertEquals(new MigrationVersion(10, 10, 10), new v10_10_10_CorrectClassName().getTargetVersion()); + } + + public static class a1_InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_a1_InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, a1_InvalidClassName::new); + } + + public static class foo1_InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_foo1_InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, foo1_InvalidClassName::new); + } + + public static class InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, InvalidClassName::new); + } + + public static class InvalidClassName_v1 extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_InvalidClassName_v1() + { + Assertions.assertThrows(IllegalArgumentException.class, InvalidClassName_v1::new); + } + + public static class v1_k_InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_v1_k_InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, v1_k_InvalidClassName::new); + } + + public static class v1_k_2_InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_v1_k_2_InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, v1_k_2_InvalidClassName::new); + } + + public static class v2147483648_InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_v2147483648_InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, v2147483648_InvalidClassName::new); + } + + public static class v___InvalidClassName extends ReflectiveVersionMigrationScriptDummy + { + } + + @Test + void invalidName_v___InvalidClassName() + { + Assertions.assertThrows(IllegalArgumentException.class, v___InvalidClassName::new); + } + + public static class ReflectiveVersionMigrationScriptDummy + extends ReflectiveVersionMigrationScript> + { + @Override + public void migrate( + final Context> context) + { + // Dummy + } + } +} diff --git a/micro-migration/src/test/java/software/xdev/micromigration/version/MigrationVersionTest.java b/micro-migration/src/test/java/software/xdev/micromigration/version/MigrationVersionTest.java new file mode 100644 index 0000000..359e117 --- /dev/null +++ b/micro-migration/src/test/java/software/xdev/micromigration/version/MigrationVersionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2021 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 software.xdev.micromigration.version; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + + +class MigrationVersionTest +{ + @Test + void checkToStringv1() + { + final MigrationVersion version = new MigrationVersion(1); + assertEquals("v1", version.toString()); + } + + @Test + void checkToStringv11() + { + final MigrationVersion version = new MigrationVersion(1, 1); + assertEquals("v1.1", version.toString()); + } + + @Test + void checkToStringv111() + { + final MigrationVersion version = new MigrationVersion(1, 1, 1); + assertEquals("v1.1.1", version.toString()); + } + + @Test + void checkToStringv0() + { + final MigrationVersion version = new MigrationVersion(0); + assertEquals("v0", version.toString()); + } + + @Test + void checkToStringvNull() + { + final MigrationVersion version = new MigrationVersion(); + assertEquals("v0", version.toString()); + } +} diff --git a/pom.xml b/pom.xml index d15d6dc..ea264ef 100644 --- a/pom.xml +++ b/pom.xml @@ -5,8 +5,8 @@ 4.0.0 software.xdev - template-placeholder-root - 1.0.0-SNAPSHOT + micro-migration-root + 2.0.1-SNAPSHOT pom @@ -15,8 +15,8 @@ - template-placeholder - template-placeholder-demo + micro-migration + micro-migration-demo diff --git a/renovate.json5 b/renovate.json5 index 2874d45..ce1352c 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -2,9 +2,19 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "rebaseWhen": "behind-base-branch", "packageRules": [ + { + "description": "Group Eclipse Store", + "matchPackagePatterns": [ + "^org.eclipse.store" + ], + "datasources": [ + "maven" + ], + "groupName": "org.eclipse.store" + }, { "description": "Ignore project internal dependencies", - "packagePattern": "^software.xdev:template-placeholder", + "packagePattern": "^software.xdev:micro-migration", "datasources": [ "maven" ],