Browse Source

:construction: Initial commit for modularization and rewrite of MaterialFX

Signed-off-by: Alessadro Parisi <alessandro.parisi406@gmail.com>
Alessadro Parisi 2 years ago
commit
33d500ebd2
100 changed files with 13574 additions and 0 deletions
  1. 42 0
      .gitignore
  2. 8 0
      .idea/.gitignore
  3. 6 0
      .idea/copyright/Default.xml
  4. 7 0
      .idea/copyright/profiles_settings.xml
  5. 21 0
      .idea/gradle.xml
  6. 3187 0
      .idea/inspectionProfiles/Project_Default.xml
  7. 10 0
      .idea/misc.xml
  8. 6 0
      .idea/vcs.xml
  9. 165 0
      LICENSE
  10. 52 0
      build.gradle
  11. 34 0
      gradle.properties
  12. BIN
      gradle/wrapper/gradle-wrapper.jar
  13. 5 0
      gradle/wrapper/gradle-wrapper.properties
  14. 234 0
      gradlew
  15. 89 0
      gradlew.bat
  16. 20 0
      modules/core/build.gradle
  17. 13 0
      modules/core/gradle.properties
  18. 176 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/animations/AnimationFactory.java
  19. 892 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/animations/Animations.java
  20. 133 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/animations/BezierEasing.java
  21. 167 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/animations/ConsumerTransition.java
  22. 117 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/animations/Interpolators.java
  23. 282 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/animations/MomentumTransition.java
  24. 69 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/TriConsumer.java
  25. 47 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/TriFunction.java
  26. 60 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/Alignment.java
  27. 79 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/AnimationsData.java
  28. 62 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/BiPredicateBean.java
  29. 114 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/CustomBounds.java
  30. 123 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/FilterBean.java
  31. 110 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/Position.java
  32. 102 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/PositionTransition.java
  33. 99 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/Size.java
  34. 49 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/SnapshotWrapper.java
  35. 110 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/DoubleRange.java
  36. 110 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/FloatRange.java
  37. 129 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/IntegerRange.java
  38. 113 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/LongRange.java
  39. 99 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/NumberRange.java
  40. 173 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/AbstractBinding.java
  41. 60 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/AbstractSource.java
  42. 205 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/BidirectionalBinding.java
  43. 203 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Binding.java
  44. 66 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/BooleanListBinding.java
  45. 135 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/ExternalSource.java
  46. 398 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/MFXBindings.java
  47. 91 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/MappedUpdater.java
  48. 76 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Mapper.java
  49. 220 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/MappingSource.java
  50. 222 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Source.java
  51. 83 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Target.java
  52. 193 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/WeakLinkedHashMap.java
  53. 76 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/base/IBinding.java
  54. 42 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/base/ISource.java
  55. 69 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/base/Updater.java
  56. 45 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/CharProperty.java
  57. 50 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/EventHandlerProperty.java
  58. 120 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/PositionProperty.java
  59. 102 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/SizeProperty.java
  60. 97 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/base/NumberRangeProperty.java
  61. 58 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/base/ResettableProperty.java
  62. 98 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/base/SynchronizedProperty.java
  63. 51 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/BiConsumerProperty.java
  64. 52 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/BiFunctionProperty.java
  65. 51 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/BiPredicateProperty.java
  66. 50 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/ComparatorProperty.java
  67. 50 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/ConsumerProperty.java
  68. 51 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/FunctionProperty.java
  69. 50 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/PredicateProperty.java
  70. 50 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/SupplierProperty.java
  71. 51 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/TriConsumerProperty.java
  72. 52 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/TriFunctionProperty.java
  73. 60 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/DoubleRangeProperty.java
  74. 60 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/FloatRangeProperty.java
  75. 60 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/IntegerRangeProperty.java
  76. 60 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/LongRangeProperty.java
  77. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableBooleanProperty.java
  78. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableDoubleProperty.java
  79. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableFloatProperty.java
  80. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableIntegerProperty.java
  81. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableLongProperty.java
  82. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableObjectProperty.java
  83. 106 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableStringProperty.java
  84. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableBooleanProperty.java
  85. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableDoubleProperty.java
  86. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableFloatProperty.java
  87. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableIntegerProperty.java
  88. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableLongProperty.java
  89. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableObjectProperty.java
  90. 96 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableSizeProperty.java
  91. 48 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableStringProperty.java
  92. 212 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedBooleanProperty.java
  93. 212 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedDoubleProperty.java
  94. 212 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedFloatProperty.java
  95. 212 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedIntegerProperty.java
  96. 211 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedLongProperty.java
  97. 214 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedObjectProperty.java
  98. 212 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedStringProperty.java
  99. 72 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/builders/CornerRadiusBuilder.java
  100. 72 0
      modules/core/src/main/java/io/github/palexdev/mfxcore/builders/InsetsBuilder.java

+ 42 - 0
.gitignore

@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 6 - 0
.idea/copyright/Default.xml

@@ -0,0 +1,6 @@
+<component name="CopyrightManager">
+  <copyright>
+    <option name="notice" value="Copyright (C) &amp;#36;today.year Parisi Alessandro - alessandro.parisi406@gmail.com&#10;This file is part of &amp;#36;project.name (https://github.com/palexdev/MaterialFX)&#10;&#10;&amp;#36;project.name is free software; you can redistribute it and/or&#10;modify it under the terms of the GNU Lesser General Public License&#10;as published by the Free Software Foundation; either version 3 of the License,&#10;or (at your option) any later version.&#10;&#10;&amp;#36;project.name is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. &#10;See the GNU Lesser General Public License for more details.&#10;&#10;You should have received a copy of the GNU Lesser General Public License&#10;along with &amp;#36;project.name; If not, see &lt;http://www.gnu.org/licenses/&gt;" />
+    <option name="myName" value="Default" />
+  </copyright>
+</component>

+ 7 - 0
.idea/copyright/profiles_settings.xml

@@ -0,0 +1,7 @@
+<component name="CopyrightManager">
+  <settings default="Default">
+    <module2copyright>
+      <element module="All" copyright="Default" />
+    </module2copyright>
+  </settings>
+</component>

+ 21 - 0
.idea/gradle.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleMigrationSettings" migrationVersion="1" />
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/modules/core" />
+            <option value="$PROJECT_DIR$/modules/localization" />
+            <option value="$PROJECT_DIR$/modules/materialfx" />
+            <option value="$PROJECT_DIR$/modules/resources" />
+          </set>
+        </option>
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 3187 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,3187 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0" is_locked="true">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="AbsoluteAlignmentInUserInterface" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractBeanReferencesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AbstractClassExtendsConcreteClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractClassNeverImplemented" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractClassWithOnlyOneDirectInheritor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractClassWithoutAbstractMethods" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractMethodCallInConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractMethodOverridesAbstractMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractMethodOverridesConcreteMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AbstractMethodWithMissingImplementations" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AccessStaticViaInstance" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AccessToNonThreadSafeStaticFieldFromInstance" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="nonThreadSafeClasses">
+        <value />
+      </option>
+      <option name="nonThreadSafeTypes" value="" />
+    </inspection_tool>
+    <inspection_tool class="AccessToStaticFieldLockedOnInstance" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ActionIsNotPreviewFriendly" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AddConversionCallMigration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AddOperatorModifier" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="AddVarianceModifier" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="AlphaUnsortedPropertiesFile" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="AmbiguousExpressionInWhenBranchMigration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AmbiguousFieldAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AmbiguousMethodCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidElementNotAllowed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAaptCrash" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAcceptsUserCertificates" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAccidentalOctal" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAdapterViewChildren" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAddJavascriptInterface" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAllCaps" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAllowAllHostnameVerifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAlwaysShowAction" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAndroidGradlePluginVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAnimatorKeep" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAnnotateVersionCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAnnotationProcessorOnCompilePath" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppBundleLocaleChanges" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppCompatCustomView" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppCompatMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppCompatResource" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppIndexingService" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppLinkUrlError" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAppLinksAutoVerify" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintApplySharedPref" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAssertionSideEffect" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAuthLeak" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAutofill" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBackButton" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintBadHostnameVerifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBatteryLife" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBidiSpoofing" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBlockedPrivateApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBottomAppBar" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBrokenIterator" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintButtonCase" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintButtonOrder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintButtonStyle" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintByteOrderMark" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCanvasSize" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCheckResult" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintClickableViewAccessibility" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCoarseFineLocation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCommitPrefEdits" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCommitTransaction" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintConstantLocale" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintContentDescription" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintConvertToWebp" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintCustomSplashScreen" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCustomViewStyleable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCustomX509TrustManager" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintCutPasteId" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDataBindingWithoutKapt" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDataExtractionRules" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDefaultLocale" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDeletedProvider" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDeprecated" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDeprecatedProvider" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDevModeObsolete" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDeviceAdmin" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDiffUtilEquals" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDisableBaselineAlignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDiscouragedApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDiscouragedPrivateApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDrawAllocation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicateActivity" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicateDefinition" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicateDivider" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicateIds" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicateIncludedIds" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicatePlatformClasses" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintDuplicateStrings" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintDuplicateUsesFeature" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintEasterEgg" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintEllipsizeMaxLines" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintEnforceUTF8" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintEnqueueWork" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExifInterface" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExpensiveAssertion" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintExpiredTargetSdkVersion" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExpiringTargetSdkVersion" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExportedContentProvider" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExportedPreferenceActivity" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExportedReceiver" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExportedService" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExtraText" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintExtraTranslation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintFileEndsWithExt" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintFindViewByIdCast" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintFontValidation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintFullBackupContent" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGetContentDescriptionOverride" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGetInstance" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGetLocales" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGifUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleCompatible" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleDependency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleDeprecated" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleDeprecatedConfiguration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleDynamicVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleGetter" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleIdeError" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradleOverrides" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradlePath" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGradlePluginVersion" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGrantAllUris" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintGridLayout" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHalfFloat" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHandlerLeak" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHardcodedDebugMode" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHardcodedText" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHardwareIds" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHighAppVersionCode" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintHighSamplingRate" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconColors" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconDensities" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconDipSize" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconDuplicates" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconDuplicatesConfig" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconExpectedSize" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintIconExtension" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconLauncherShape" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconLocation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconMissingDensityFolder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconMixedNinePatch" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconNoDpi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIconXmlAndPng" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIgnoreWithoutReason" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIllegalResourceRef" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintImplicitSamInstance" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintImpliedQuantity" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintImpliedTouchscreenHardware" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInOrMmUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIncludeLayoutParam" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIncompatibleMediaBrowserServiceCompatVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInconsistentArrays" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInconsistentLayout" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInefficientWeight" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInflateParams" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInlinedApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInnerclassSeparator" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInsecureBaseConfiguration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInstantApps" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInstantiatable" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIntentFilterExportedReceiver" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIntentFilterUniqueDataAttributes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintIntentReset" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidAnalyticsName" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidId" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidImeActionId" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidNavigation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidPermission" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidResourceFolder" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidUsesTagAttribute" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidVectorPath" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidWakeLockTag" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintInvalidWearFeatureAttribute" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintJavaPluginLanguageLevel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintJavascriptInterface" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintJcenterRepositoryObsolete" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintJobSchedulerService" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintKeyboardInaccessibleWidget" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintKotlinPropertyAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintKtxExtensionAvailable" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLabelFor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLambdaLast" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintLaunchActivityFromNotification" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLeanbackUsesWifi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLibraryCustomView" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLifecycleAnnotationProcessorWithJava8" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLocalSuppress" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLocaleFolder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLockedOrientationActivity" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLogConditional" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintLogTagMismatch" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintLongLogTag" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMangledCRLF" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintManifestOrder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintManifestResource" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMenuTitle" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMergeMarker" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMergeRootFrame" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMinSdkTooLow" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintMipmapIcons" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingApplicationIcon" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingBackupPin" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingClass" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingConstraints" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingDefaultResource" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingFirebaseInstanceTokenRefresh" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingId" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingIntentFilterForMediaSearch" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingLeanbackLauncher" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingLeanbackSupport" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingMediaBrowserServiceIntentFilter" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingOnPlayFromSearch" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingPermission" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingPrefix" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingQuantity" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingSuperCall" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingTranslation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingTvBanner" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMockLocation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMotionLayoutInvalidSceneFileReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMotionLayoutMissingId" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMotionSceneFileValidationError" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMultipleUsesSdk" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMutatingSharedPrefs" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNamespaceTypo" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNegativeMargin" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintNestedScrolling" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNestedWeights" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNetworkSecurityConfig" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNewApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNewerVersionAvailable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintNfcTechWhitespace" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNoHardKeywords" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintNonConstantResourceId" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNonResizeableActivity" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNotConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNotInterpolated" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNotSibling" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNotificationIconCompatibility" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNotificationTrampoline" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintNotifyDataSetChanged" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintObjectAnimatorBinding" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintObsoleteLayoutParam" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintObsoleteSdkInt" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOldTargetApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOnClick" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOrientation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOutdatedLibrary" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOverdraw" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOverride" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintOverrideAbstract" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPackageManagerGetSignatures" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPackagedPrivateKey" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintParcelClassLoader" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintParcelCreator" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPendingBindings" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPermissionImpliesUnsupportedChromeOsHardware" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintPermissionImpliesUnsupportedHardware" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPinSetExpiry" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPluralsCandidate" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPrivateApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPrivateResource" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintProguard" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintProguardSplit" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPropertyEscape" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintProtectedPermissions" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintProxyPassword" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPxUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintQueryAllPackagesPermission" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintQueryPermissionsNeeded" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRange" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRecycle" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRecyclerView" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRedundantLabel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRedundantNamespace" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintReferenceType" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRegistered" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintRelativeOverlap" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRemoteViewLayout" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRequiredSize" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRequiresFeature" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintResAuto" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintResourceAsColor" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintResourceCycle" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintResourceName" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintResourceType" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRestrictedApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRiskyLibrary" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRtlCompat" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRtlEnabled" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRtlHardcoded" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintRtlSymmetry" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSQLiteString" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSSLCertificateSocketFactoryCreateSocket" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSSLCertificateSocketFactoryGetInsecure" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintScopedStorage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintScrollViewCount" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintScrollViewSize" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSdCardPath" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSecureRandom" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSelectableText" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintServiceCast" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSetJavaScriptEnabled" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSetTextI18n" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSetWorldReadable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSetWorldWritable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintShiftFlags" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintShortAlarm" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintShowToast" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSignatureOrSystemPermissions" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSimpleDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSlices" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSmallSp" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSoonBlockedPrivateApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSourceLockedOrientationActivity" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSpUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStateListReachable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStaticFieldLeak" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStopShip" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintStringEscaping" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStringFormatCount" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStringFormatInvalid" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStringFormatMatches" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintStringShouldBeInt" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSupportAnnotationUsage" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSuspicious0dp" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSuspiciousImport" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSwitchIntDef" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintSyntheticAccessor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintTestAppLink" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTextFields" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTextViewEdits" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTileProviderPermissions" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTooDeepLayout" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTooManyViews" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTranslucentOrientation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTrustAllX509TrustManager" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTypographyDashes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTypographyEllipsis" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTypographyFractions" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTypographyOther" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintTypographyQuotes" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintTypos" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUastImplementation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUniqueConstants" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUniquePermission" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnknownId" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnknownIdInLayout" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnknownNullness" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintUnlocalizedSms" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnpackedNativeCode" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintUnprotectedSMSBroadcastReceiver" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnsafeDynamicallyLoadedCode" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnsafeNativeCodeLocation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnsafeProtectedBroadcastReceiver" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnspecifiedImmutableFlag" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnsupportedChromeOsCameraSystemFeature" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnsupportedChromeOsHardware" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintUnsupportedTvHardware" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUntranslatable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnusedAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnusedIds" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintUnusedQuantity" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUnusedResources" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUsableSpace" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUseAlpha2" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUseCheckPermission" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUseCompoundDrawables" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUseOfBundledGooglePlayServices" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUseSparseArrays" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUseValueOf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUselessLeaf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUselessParent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUsesMinSdkAttributes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUsingC2DM" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintUsingHttp" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintValidActionsXml" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintValidFragment" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintValidRestrictions" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintVectorDrawableCompat" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintVectorPath" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintVectorRaster" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintViewBindingType" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintViewConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintViewHolder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintVisibleForTests" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWakelockTimeout" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWatchFaceEditor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWearStandaloneAppFlag" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWearableBindListener" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWearableConfigurationAction" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWebViewApiAvailability" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWebViewClientOnReceivedSslError" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWebViewLayout" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWebpUnsupported" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWeekBasedYear" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWifiManagerLeak" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWifiManagerPotentialLeak" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWorldReadableFiles" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWorldWriteableFiles" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongCall" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongCase" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongConstant" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongFolder" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongRegion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongThread" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWrongThreadInterprocedural" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintWrongViewCast" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintXmlEscapeNeeded" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidMissingOnClickHandler" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidNonConstantResIdsInSwitch" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidRoomQuestionMarkBindParameter" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidUnresolvableTag" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidUnresolvedRoomSqlReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularAmbiguousComponentTag" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularCliAddDependency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AngularInaccessibleComponentMemberInAotMode" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AngularIncorrectTemplateDefinition" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularInsecureBindingToEvent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AngularInvalidAnimationTriggerAssignment" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularInvalidEntryComponent" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularInvalidI18nAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AngularInvalidImportedOrDeclaredSymbol" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularInvalidSelector" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularInvalidTemplateReferenceVariable" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularMissingEventHandler" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularMissingOrInvalidDeclarationInModule" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularMultipleStructuralDirectives" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularNonEmptyNgContent" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularRecursiveModuleImportExport" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularUndefinedBinding" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularUndefinedModuleExport" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AngularUndefinedTag" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="Annotation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AnnotationClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Annotator" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="Anonymous2MethodRef" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AnonymousClassComplexity" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="AnonymousClassMethodCount" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="1" />
+    </inspection_tool>
+    <inspection_tool class="AnonymousClassVariableHidesContainingMethodVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AnonymousFunctionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AnonymousHasLambdaAlternative" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AnonymousInnerClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AnonymousInnerClassMayBeStatic" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AntDuplicateTargetsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AntMissingPropertiesFileInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AntResolveInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ArgNamesErrorsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ArgNamesWarningsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AroundAdviceStyleInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArrayCanBeReplacedWithEnumValues" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ArrayCreationWithoutNewKeyword" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ArrayEquality" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ArrayEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArrayHashCode" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArrayInDataClass" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArrayLengthInLoopCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ArrayObjectsEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArraysAsListWithZeroOrOneArgument" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AssertBetweenInconvertibleTypes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AssertEqualsCalledOnArray" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssertEqualsMayBeAssertSame" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssertMessageNotString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssertStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssertWithSideEffects" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AssertWithoutMessage" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssertionCanBeIf" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="AssignmentOrReturnOfFieldWithMutableType" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentResultUsedJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentToCatchBlockParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AssignmentToForLoopParameter" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_checkForeachParameters" value="true" />
+    </inspection_tool>
+    <inspection_tool class="AssignmentToForLoopParameterJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentToFunctionParameterJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentToLambdaParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentToMethodParameter" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreTransformationOfOriginalParameter" value="false" />
+    </inspection_tool>
+    <inspection_tool class="AssignmentToNull" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentToStaticFieldFromInstanceMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentToSuperclassField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AssignmentUsedAsCondition" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AsyncMethodInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AtomicFieldUpdaterIssues" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AtomicFieldUpdaterNotStaticFinal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AutoBoxing" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreAddedToCollection" value="false" />
+    </inspection_tool>
+    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AutoUnboxing" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AwaitNotInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AwaitWithoutCorrespondingSignal" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BadExceptionCaught" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="exceptionsString" value="" />
+      <option name="exceptions">
+        <value />
+      </option>
+    </inspection_tool>
+    <inspection_tool class="BadExceptionDeclared" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="exceptionsString" value="" />
+      <option name="exceptions">
+        <value />
+      </option>
+      <option name="ignoreTestCases" value="false" />
+      <option name="ignoreLibraryOverrides" value="false" />
+    </inspection_tool>
+    <inspection_tool class="BadExceptionThrown" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="exceptionsString" value="" />
+      <option name="exceptions">
+        <value />
+      </option>
+    </inspection_tool>
+    <inspection_tool class="BadExpressionStatementJS" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="BadOddness" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BigDecimalEquals" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BigDecimalLegacyMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BigDecimalMethodWithoutRoundingCalled" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BindingAnnotationWithoutInject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BintrayPublishingPlugin" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BlockMarkerComments" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BlockStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BlockingMethodInNonBlockingContext" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BooleanConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BooleanExpressionMayBeConditional" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="BooleanLiteralArgument" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="BooleanMethodIsAlwaysInverted" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
+    <inspection_tool class="BooleanMethodNameMustStartWithQuestion" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreBooleanMethods" value="false" />
+      <option name="ignoreInAnnotationInterface" value="true" />
+      <option name="onlyWarnOnBaseMethods" value="true" />
+      <option name="questionString" value="are,can,check,contains,could,endsWith,equals,has,is,matches,must,shall,should,startsWith,was,were,will,would" />
+    </inspection_tool>
+    <inspection_tool class="BooleanParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BooleanVariableAlwaysNegated" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BoundFieldAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BoundedWildcard" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BoxingBoxedValue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BreakStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BreakStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BreakStatementWithLabel" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BreakStatementWithLabelJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BulkFileAttributesRead" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BusyWait" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="BvConfigDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="BvConstraintMappingsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CStyleArrayDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CachedNumberConstructorCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CallToNativeMethodWhileLocked" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CallToSimpleGetterInClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreGetterCallsOnOtherObjects" value="false" />
+      <option name="onlyReportPrivateGetter" value="false" />
+    </inspection_tool>
+    <inspection_tool class="CallToSimpleSetterInClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreSetterCallsOnOtherObjects" value="false" />
+      <option name="onlyReportPrivateSetter" value="false" />
+    </inspection_tool>
+    <inspection_tool class="CallToStringConcatCanBeReplacedByOperator" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CallToSuspiciousStringMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CallerJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CallingSubscribeInNonBlockingScope" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="REPORT_CLASSES" value="false" />
+      <option name="REPORT_METHODS" value="false" />
+      <option name="REPORT_FIELDS" value="true" />
+    </inspection_tool>
+    <inspection_tool class="CanBeParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CanBePrimaryConstructorProperty" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CanBeVal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CanSealedSubClassBeObject" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="CapturingCleaner" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CascadeIf" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="CastCanBeRemovedNarrowingVariableType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CastConflictsWithInstanceof" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CastDueToProgressionResolutionChangeMigration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CastThatLosesPrecision" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreIntegerCharCasts" value="false" />
+      <option name="ignoreOverflowingByteCasts" value="false" />
+    </inspection_tool>
+    <inspection_tool class="CastToIncompatibleInterface" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CatchMayIgnoreException" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CaughtExceptionImmediatelyRethrown" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CdiAlternativeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiDecoratorInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiDisposerMethodInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiDomBeans" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CdiInjectInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiInjectionPointsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CdiInterceptorInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiManagedBeanInconsistencyInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiNormalScopeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CdiObservesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiScopeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CdiSpecializesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiStereotypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiStereotypeRestrictionsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiTypedAnnotationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CdiUnknownProducersForDisposerMethodInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CdiUnproxyableBeanTypesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ChainedEquality" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ChainedEqualityJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ChainedFunctionCallJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ChainedMethodCall" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreFieldInitializations" value="true" />
+      <option name="m_ignoreThisSuperCalls" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ChangeToMethod" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ChangeToOperator" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ChannelResource" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="insideTryAllowed" value="false" />
+    </inspection_tool>
+    <inspection_tool class="CharUsedInArithmeticContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CharacterComparison" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CharsetObjectCanBeUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CheckDtdRefs" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CheckEmptyScriptTag" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CheckForOutOfMemoryOnLargeArrayAllocation" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="64" />
+    </inspection_tool>
+    <inspection_tool class="CheckImageSize" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CheckNodeTest" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CheckTagEmptyBody" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CheckValidXmlInScriptTagBody" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CheckXmlFileWithXercesValidator" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CheckedExceptionClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClashingGetters" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClashingTraitMethods" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ClassCanBeRecord" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ClassComplexity" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="80" />
+    </inspection_tool>
+    <inspection_tool class="ClassCoupling" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_includeJavaClasses" value="false" />
+      <option name="m_includeLibraryClasses" value="false" />
+      <option name="m_limit" value="15" />
+    </inspection_tool>
+    <inspection_tool class="ClassEscapesItsScope" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ClassGetClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ClassHasNoToStringMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="excludeClassNames" value="" />
+      <option name="excludeException" value="true" />
+      <option name="excludeDeprecated" value="true" />
+      <option name="excludeEnum" value="false" />
+      <option name="excludeAbstract" value="false" />
+      <option name="excludeTestCode" value="false" />
+      <option name="excludeInnerClasses" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ClassIndependentOfModule" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassInheritanceDepth" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="2" />
+    </inspection_tool>
+    <inspection_tool class="ClassInitializer" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassInitializerMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ClassLoaderInstantiation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassMayBeInterface" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ClassName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ClassNameDiffersFromFileName" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassNamePrefixedWithPackageName" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassNameSameAsAncestorName" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassNestingDepth" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="1" />
+    </inspection_tool>
+    <inspection_tool class="ClassNewInstance" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassOnlyUsedInOneModule" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassOnlyUsedInOnePackage" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassReferencesSubclass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassUnconnectedToPackage" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassWithMultipleLoggers" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerNamesString" value="java.util.logging.Logger,org.slf4j.Logger,org.apache.commons.logging.Log,org.apache.log4j.Logger,org.apache.logging.log4j.Logger" />
+    </inspection_tool>
+    <inspection_tool class="ClassWithOnlyPrivateConstructors" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassWithTooManyDependencies" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="ClassWithTooManyDependents" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="ClassWithTooManyTransitiveDependencies" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="35" />
+    </inspection_tool>
+    <inspection_tool class="ClassWithTooManyTransitiveDependents" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="35" />
+    </inspection_tool>
+    <inspection_tool class="ClassWithoutConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ClassWithoutLogger" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerNamesString" value="java.util.logging.Logger,org.slf4j.Logger,org.apache.commons.logging.Log,org.apache.log4j.Logger,org.apache.logging.log4j.Logger" />
+      <option name="ignoreSuperLoggers" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ClassWithoutNoArgConstructor" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreClassesWithNoConstructors" value="true" />
+    </inspection_tool>
+    <inspection_tool class="CloneCallsConstructors" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CloneDeclaresCloneNotSupported" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CloneInNonCloneableClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CloneReturnsClassType" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CloneableClassInSecureContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CloneableImplementsClone" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreCloneableDueToInheritance" value="true" />
+    </inspection_tool>
+    <inspection_tool class="CodeBlock2Expr" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CollectionAddAllCanBeReplacedWithConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CollectionAddedToSelf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CollectionContainsUrl" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CollectionsFieldAccessReplaceableByMethodCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CollectionsMustHaveInitialCapacity" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CommaExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CommentedOutCode" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ComparableImplementedButEqualsNotOverridden" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ComparatorCombinators" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ComparatorMethodParameterNotUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ComparatorNotSerializable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ComparatorResultComparison" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CompareToUsesNonFinalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ComparisonOfShortAndChar" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ComparisonToNaN" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ComplexRedundantLet" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ComponentNotRegistered" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="CHECK_ACTIONS" value="true" />
+      <option name="IGNORE_NON_PUBLIC" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ComponentRegistrationProblems" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ComposeMissingKeys" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="ComposeUnknownKeys" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ComposeUnknownValues" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ComposeUnquotedPorts" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConditionCoveredByFurtherCondition" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConditionSignal" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConditionalBreakInInfiniteLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConditionalCanBeOptional" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConditionalCanBePushedInsideExpression" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConditionalExpression" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConditionalExpressionWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConditionalExpressionWithIdenticalBranchesJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConfigurationProperties" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ConflictingAnnotations" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConflictingExtensionProperty" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConfusingElse" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="reportWhenNoStatementFollow" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ConfusingFloatingPointLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConfusingFloatingPointLiteralJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConfusingMainMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConfusingOctalEscape" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConfusingPlusesOrMinusesJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConnectionResource" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstPropertyName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConstantAssertArgument" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantAssertCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantConditionIf" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConstantConditionalExpression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConstantConditionalExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
+      <option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ConstantDeclaredInAbstractClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantDeclaredInInterface" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantExpression" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConstantMathCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantOnLHSOfComparisonJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantOnRHSOfComparisonJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantOnWrongSideOfComparison" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstantValueVariableUse" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConstructorCount" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreDeprecatedConstructors" value="false" />
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="ContextComponentScanInconsistencyInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ContextJavaBeanUnresolvedMethodsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ContinueOrBreakFromFinallyBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ContinueOrBreakFromFinallyBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ContinueStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ContinueStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ContinueStatementWithLabel" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ContinueStatementWithLabelJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Contract" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ControlFlowStatementWithoutBraces" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ControlFlowWithEmptyBody" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Convert2Diamond" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Convert2Lambda" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Convert2MethodRef" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Convert2streamapi" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConvertArgumentToSet" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConvertCallChainIntoSequence" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ConvertJavadoc" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConvertLambdaToReference" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConvertNaNEquality" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConvertOldAnnotations" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConvertPairConstructorToToFunction" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConvertReferenceToLambda" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConvertSecondaryConstructorToPrimary" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConvertToBasicLatin" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ConvertToStringTemplate" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ConvertTryFinallyToUseCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ConvertTwoComparisonsToRangeCheck" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="CopyConstructorMissesField" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CopyWithoutNamedArguments" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="CovariantEquals" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CriteriaApiResolveInspection" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="CssBrowserCompatibilityForProperties" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CssConvertColorToHexInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CssConvertColorToRgbInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CssInvalidAtRule" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidCharsetRule" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidFunction" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidHtmlTagReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidImport" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidMediaFeature" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidPropertyValue" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssInvalidPseudoSelector" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssMissingComma" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssMissingSemicolon" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CssNegativeValue" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssNoGenericFontName" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssNonIntegerLengthInPixels" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssOverwrittenProperties" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssRedundantUnit" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssReplaceWithShorthandSafely" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="CssReplaceWithShorthandUnsafely" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="CssUnknownProperty" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="myCustomPropertiesEnabled" value="false" />
+      <option name="myIgnoreVendorSpecificProperties" value="false" />
+      <option name="myCustomPropertiesList">
+        <value>
+          <list size="0" />
+        </value>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="CssUnknownTarget" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssUnresolvedClassInComposesRule" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssUnresolvedCustomProperty" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssUnusedSymbol" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CucumberExamplesColon" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CucumberJavaStepDefClassInDefaultPackage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CucumberJavaStepDefClassIsPublic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CucumberMissedExamples" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CucumberTableInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CucumberUndefinedStep" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="CustomClassloader" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CustomSecurityManager" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CyclicClassDependency" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CyclicPackageDependency" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CyclomaticComplexity" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="CyclomaticComplexityJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="DanglingJavadoc" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DataClassPrivateConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DataProviderReturnType" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DateToString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DebuggerStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DeclareCollectionAsInterface" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreLocalVariables" value="false" />
+      <option name="ignorePrivateMethodsAndFields" value="false" />
+    </inspection_tool>
+    <inspection_tool class="DeclareParentsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DefaultAnnotationParam" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DefaultFileTemplate" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="CHECK_FILE_HEADER" value="true" />
+      <option name="CHECK_TRY_CATCH_SECTION" value="true" />
+      <option name="CHECK_METHOD_BODY" value="true" />
+    </inspection_tool>
+    <inspection_tool class="DefaultNotLastCaseInSwitch" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DefaultNotLastCaseInSwitchJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DeferredIsResult" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="DeferredResultUnused" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DelegatesTo" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DelegationToVarProperty" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Dependency" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DeprecatedCallableAddReplaceWith" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="DeprecatedClassUsageInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DeprecatedGradleDependency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DeprecatedIsStillUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DeprecatedLombok" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DeprecatedMavenDependency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Deprecation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DesignForExtension" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Destructure" enabled="false" level="INFO" enabled_by_default="false" />
+    <inspection_tool class="DestructuringWrongName" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DevKitPropertiesQuotesValidation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DialogTitleCapitalization" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DiamondCanBeReplacedWithExplicitTypeArguments" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="DifferentKotlinGradleVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DifferentKotlinMavenVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DifferentMavenStdlibVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DifferentStdlibGradleVersion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DirectUseOfResultType" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="DisjointPackage" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DivideByZero" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DivideByZeroJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DockerFileAddOrCopySemantic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DockerFileArgumentCount" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DockerFileAssignments" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DockerFileRunCommandMissingContinuation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DocumentWriteJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DollarSignInName" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DoubleBraceInitialization" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="DoubleCheckedLocking" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreOnVolatileVariables" value="false" />
+    </inspection_tool>
+    <inspection_tool class="DoubleLiteralMayBeFloatLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DoubleNegation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DriverManagerGetConnection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DuplicateBranchesInSwitch" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="DuplicateCondition" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreSideEffectConditions" value="true" />
+    </inspection_tool>
+    <inspection_tool class="DuplicateConditionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DuplicateExpressions" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="DuplicateMnemonic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DuplicatePropertyInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DuplicateStringLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="MIN_STRING_LENGTH" value="5" />
+      <option name="IGNORE_PROPERTY_KEYS" value="false" />
+    </inspection_tool>
+    <inspection_tool class="DuplicateThrows" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DuplicatedBeanNamesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <Languages>
+        <language minSize="125" name="Java" />
+      </Languages>
+    </inspection_tool>
+    <inspection_tool class="DuplicatedDataProviderNames" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="DynamicRegexReplaceableByCompiledPattern" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DynamicallyGeneratedCodeJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ELDeferredExpressionsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ELMethodSignatureInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ELSpecValidationInJSP" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ELValidationInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6BindWithArrowFunction" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6CheckImport" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6ClassMemberInitializationOrder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertIndexedForToForOf" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertLetToConst" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertModuleExportToExport" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertRequireIntoImport" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertToForOf" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertVarToLetConst" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6DestructuringVariablesMerge" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6MissingAwait" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6PossiblyAsyncFunction" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6PreferShortImport" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6RedundantAwait" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6RedundantNestingInTemplateLiteral" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6ShorthandObjectProperty" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ES6TopLevelAwaitExpression" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="ES6UnusedImports" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigCharClassLetterRedundancy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigCharClassRedundancy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigDeprecatedDescriptor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigEmptyHeader" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigEmptySection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigEncoding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigHeaderUniqueness" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigKeyCorrectness" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigListAcceptability" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigMissingRequiredDeclaration" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigNoMatchingFiles" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigNumerousWildcards" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigOptionRedundancy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigPairAcceptability" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigPartialOverride" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigPatternEnumerationRedundancy" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigPatternRedundancy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigReferenceCorrectness" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigRootDeclarationCorrectness" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigRootDeclarationUniqueness" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigShadowedOption" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigShadowingOption" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigSpaceInHeader" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigUnexpectedComma" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigUnusedDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigValueCorrectness" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigValueUniqueness" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="EditorConfigWildcardRedundancy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyCatchBlockJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EmptyClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignorableAnnotations">
+        <value />
+      </option>
+      <option name="ignoreClassWithParameterization" value="false" />
+      <option name="ignoreThrowables" value="true" />
+      <option name="commentsAreContent" value="true" />
+    </inspection_tool>
+    <inspection_tool class="EmptyDirectory" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EmptyFinallyBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyFinallyBlockJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EmptyInitializer" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyRange" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyStatementBody" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_reportEmptyBlocks" value="true" />
+    </inspection_tool>
+    <inspection_tool class="EmptyStatementBodyJS" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_reportEmptyBlocks" value="false" />
+    </inspection_tool>
+    <inspection_tool class="EmptySynchronizedStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyTryBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EmptyTryBlockJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EndlessStream" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EnhancedSwitchBackwardMigration" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="EnhancedSwitchMigration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EnumClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EnumEntryName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="EnumSwitchStatementWhichMissesCases" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreSwitchStatementsWithDefault" value="true" />
+    </inspection_tool>
+    <inspection_tool class="EnumerationCanBeIteration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualsAndHashcode" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualsBetweenInconvertibleTypes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EqualsCalledOnEnumConstant" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualsHashCodeCalledOnUrl" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualsOnSuspiciousObject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EqualsOrHashCode" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EqualsReplaceableByObjectsCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="EqualsUsesNonFinalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualsWhichDoesntCheckParameterClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="EqualsWithItself" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ErrorRethrown" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Eslint" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExceptionCaughtLocallyJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ExceptionFromCatchWhichDoesntWrap" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreGetMessage" value="false" />
+      <option name="ignoreCantWrap" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ExceptionNameDoesntEndWithException" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExceptionPackage" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExcessiveLambdaUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ExcessiveRangeCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ExpectedExceptionNeverThrown" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExpectedExceptionNeverThrownTestNG" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExplicitArgumentCanBeLambda" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ExplicitArrayFilling" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ExplicitThis" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ExpressionMayBeFactorized" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ExtendsAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ExtendsConcreteCollection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExtendsObject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ExtendsThread" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExtendsThrowable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExtendsUtilityClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExternalizableWithSerializationMethods" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ExternalizableWithoutPublicNoArgConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FakeJvmFieldConstant" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FallThroughInSwitchStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FallthruInSwitchStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FeatureEnvy" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreTestCases" value="false" />
+    </inspection_tool>
+    <inspection_tool class="FieldAccessNotGuarded" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FieldAccessedSynchronizedAndUnsynchronized" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="countGettersAndSetters" value="false" />
+    </inspection_tool>
+    <inspection_tool class="FieldCanBeLocal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FieldCount" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_countConstantFields" value="false" />
+      <option name="m_considerStaticFinalFieldsConstant" value="false" />
+      <option name="myCountEnumConstants" value="false" />
+      <option name="m_limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="FieldHasSetterButNoGetter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FieldHidesSuperclassField" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreInvisibleFields" value="true" />
+    </inspection_tool>
+    <inspection_tool class="FieldMayBeFinal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FieldMayBeStatic" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FieldNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FieldNotUsedInToString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FileEqualsUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FillPermitsList" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="FinalClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FinalMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FinalMethodInFinalClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FinalPrivateMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FinalStaticMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Finalize" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreTrivialFinalizers" value="true" />
+    </inspection_tool>
+    <inspection_tool class="FinalizeNotProtected" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FinallyBlockCannotCompleteNormally" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FloatingPointEquality" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FloatingPointLiteralPrecision" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="FlowJSConfig" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FlowJSCoverage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="FlowJSError" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="FlowJSFlagCommentPlacement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FoldExpressionIntoStream" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="FoldInitializerAndIfToElvis" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ForCanBeForeach" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="REPORT_INDEXED_LOOP" value="true" />
+      <option name="ignoreUntypedCollections" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ForEachParameterNotUsed" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ForLoopReplaceableByWhile" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreLoopsWithoutConditions" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ForLoopReplaceableByWhileJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreLoopsWithoutConditions" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ForLoopThatDoesntUseLoopVariableJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ForLoopWithMissingComponent" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreCollectionLoops" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ForeachStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FormSpellChecking" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ForwardCompatibility" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FrequentlyUsedInheritorInspection" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="FromClosedRangeMigration" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="FtlCallsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="FtlDeprecatedBuiltInsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FtlFileReferencesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="FtlImportCallInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="FtlReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FtlTypesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FtlWellformednessInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="FunctionELReferenceInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="FunctionName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="FunctionNamingConventionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="FunctionWithInconsistentReturnsJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FunctionWithLambdaExpressionBody" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="FunctionWithMultipleLoopsJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FunctionWithMultipleReturnPointsJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FunctionalExpressionCanBeFolded" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="FuseStreamOperations" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GherkinBrokenTableInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="GherkinMisplacedBackground" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="GherkinScenarioToScenarioOutline" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="Glassfish" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="GrAnnotationReferencingUnknownIdentifiers" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrDeprecatedAPIUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrEqualsBetweenInconvertibleTypes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrFinalVariableAccess" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrMethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrNamedVariantLabels" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrPOJO" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrPackage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrPermitsClause" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="GrReassignedInClosureLocalVar" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrStringStyleViolation" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="GrSwitchExhaustivenessCheck" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessaryAlias" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessaryDefModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessaryFinalModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessaryNonSealedModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessaryPublicModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessarySealedModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessarySemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnresolvedAccess" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="GradleKotlinxCoroutinesDeprecation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="GradlePackageUpdate" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="GradlePackageVersionRange" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrazieInspection" enabled="true" level="GRAMMAR_ERROR" enabled_by_default="true" />
+    <inspection_tool class="GroovyAccessToStaticFieldLockedOnInstance" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyAccessibility" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyAssignabilityCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyAssignmentCanBeOperatorAssignment" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreLazyOperators" value="true" />
+      <option name="ignoreObscureOperators" value="false" />
+    </inspection_tool>
+    <inspection_tool class="GroovyAssignmentToForLoopParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyAssignmentToMethodParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyBreak" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyBusyWait" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyConditional" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyConditionalCanBeConditionalCall" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="GroovyConditionalCanBeElvis" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="GroovyConditionalWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyConstantConditional" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyConstantIfStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyConstantNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[A-Z\d]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovyConstructorNamedArguments" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyContinue" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyContinueOrBreakFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyDivideByZero" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyDocCheck" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="GroovyDoubleCheckedLocking" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreOnVolatileVariables" value="false" />
+    </inspection_tool>
+    <inspection_tool class="GroovyDoubleNegation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyDuplicateSwitchBranch" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyEmptyCatchBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyEmptyFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyEmptyStatementBody" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyEmptySyncBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyEmptyTryBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyFallthrough" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyGStringKey" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyIfStatementWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyIfStatementWithTooManyBranches" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="GroovyImplicitNullArgumentCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyInArgumentCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyInfiniteLoopStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyInfiniteRecursion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyInstanceMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovyInstanceVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="m_[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="1" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovyLabeledStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyListGetCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyListSetCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyLocalVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovyLoopStatementThatDoesntLoop" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyMapGetCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyMapPutCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyMethodParameterCount" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="GroovyMethodWithMoreThanThreeNegations" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyMissingReturnStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyMultipleReturnPointsPerMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="1" />
+    </inspection_tool>
+    <inspection_tool class="GroovyNegatedConditional" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNegatedIf" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNestedAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNestedConditional" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNestedSwitch" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNestedSynchronizedStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNonShortCircuitBoolean" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyNotifyWhileNotSynchronized" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyOctalInteger" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyOverlyComplexArithmeticExpression" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="GroovyOverlyComplexBooleanExpression" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="GroovyOverlyComplexMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="GroovyOverlyLongMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="30" />
+    </inspection_tool>
+    <inspection_tool class="GroovyOverlyNestedMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="GroovyParameterNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovyPointlessArithmetic" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyPointlessBoolean" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyPublicFieldAccessedInSynchronizedContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyRangeTypeCheck" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyResultOfAssignmentUsed" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyResultOfIncrementOrDecrementUsed" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyResultOfObjectAllocationIgnored" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyReturnFromClosureCanBeImplicit" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyReturnFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovySillyAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyStaticMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovyStaticVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="s_[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="4" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="GroovySwitchStatementWithNoDefault" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovySynchronizationOnNonFinalField" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovySynchronizationOnThis" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovySynchronizationOnVariableInitializedWithLiteral" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovySynchronizedMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovySystemRunFinalizersOnExit" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyThreadStopSuspendResume" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyThrowFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyTrivialConditional" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyTrivialIf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUncheckedAssignmentOfMemberOfRawType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnconditionalWait" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyUnnecessaryContinue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnnecessaryReturn" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnreachableStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnsynchronizedMethodOverridesSynchronizedMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUntypedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyUnusedAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnusedCatchParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnusedDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyUnusedIncOrDec" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyVariableCanBeFinal" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyVariableNotAssigned" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GroovyWaitCallNotInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyWaitWhileNotSynchronized" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GroovyWhileLoopSpinsOnField" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreNonEmtpyLoops" value="false" />
+    </inspection_tool>
+    <inspection_tool class="Guava" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HamlNestedTagContent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HardCodedStringLiteral" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreForAssertStatements" value="true" />
+      <option name="ignoreForExceptionConstructors" value="true" />
+      <option name="ignoreForSpecifiedExceptionConstructors" value="" />
+      <option name="ignoreForJUnitAsserts" value="true" />
+      <option name="ignoreForClassReferences" value="true" />
+      <option name="ignoreForPropertyKeyReferences" value="true" />
+      <option name="ignoreForNonAlpha" value="true" />
+      <option name="ignoreAssignedToConstants" value="false" />
+      <option name="ignoreToString" value="false" />
+      <option name="nonNlsCommentPattern" value="NON-NLS" />
+    </inspection_tool>
+    <inspection_tool class="HardcodedFileSeparators" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_recognizeExampleMediaType" value="false" />
+    </inspection_tool>
+    <inspection_tool class="HardcodedLineSeparators" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="HardwiredNamespacePrefix" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HasPlatformType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="HashCodeUsesNonFinalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="HibernateConfigDomFacetInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HibernateConfigDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="HibernateMappingDatasourceDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="HibernateMappingDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="HibernateResource" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="insideTryAllowed" value="false" />
+    </inspection_tool>
+    <inspection_tool class="HtmlDeprecatedAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlDeprecatedTag" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlExtraClosingTag" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlFormInputWithoutLabel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlMissingClosingTag" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="HtmlNonExistentInternetResource" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="HtmlPresentationalElement" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="HtmlRequiredAltAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlRequiredLangAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlRequiredSummaryAttribute" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="HtmlRequiredTitleAttribute" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="HtmlRequiredTitleElement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlTagCanBeJavadocTag" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="HtmlUnknownAnchorTarget" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="myValues">
+        <value>
+          <list size="0" />
+        </value>
+      </option>
+      <option name="myCustomValuesEnabled" value="true" />
+    </inspection_tool>
+    <inspection_tool class="HtmlUnknownBooleanAttribute" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="myValues">
+        <value>
+          <list size="6">
+            <item index="0" class="java.lang.String" itemvalue="nobr" />
+            <item index="1" class="java.lang.String" itemvalue="noembed" />
+            <item index="2" class="java.lang.String" itemvalue="comment" />
+            <item index="3" class="java.lang.String" itemvalue="noscript" />
+            <item index="4" class="java.lang.String" itemvalue="embed" />
+            <item index="5" class="java.lang.String" itemvalue="script" />
+          </list>
+        </value>
+      </option>
+      <option name="myCustomValuesEnabled" value="true" />
+    </inspection_tool>
+    <inspection_tool class="HtmlUnknownTarget" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HttpClientUnresolvedVariable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HttpRequestContentLengthIsIgnored" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HttpRequestPlaceholder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="I18nForm" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IOResource" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoredTypesString" value="java.io.ByteArrayOutputStream,java.io.ByteArrayInputStream,java.io.StringBufferInputStream,java.io.CharArrayWriter,java.io.CharArrayReader,java.io.StringWriter,java.io.StringReader" />
+      <option name="insideTryAllowed" value="false" />
+    </inspection_tool>
+    <inspection_tool class="IOStreamConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IdempotentLoopBody" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IfCanBeAssertion" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="IfCanBeSwitch" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="minimumBranches" value="3" />
+      <option name="suggestIntSwitches" value="false" />
+      <option name="suggestEnumSwitches" value="false" />
+    </inspection_tool>
+    <inspection_tool class="IfStatementMissingBreakInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IfStatementWithIdenticalBranches" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="IfStatementWithIdenticalBranchesJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IfStatementWithTooManyBranches" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="IfStatementWithTooManyBranchesJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="IfThenToElvis" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="IfThenToSafeAccess" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="IgnoreFileDuplicateEntry" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IgnoreResultOfCall" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_reportAllNonLibraryCalls" value="false" />
+      <option name="callCheckString" value="java.io.File,.*,java.io.InputStream,read|skip|available|markSupported,java.io.Reader,read|skip|ready|markSupported,java.lang.AbstractStringBuilder,capacity|codePointAt|codePointBefore|codePointCount|indexOf|lastIndexOf|offsetByCodePoints|substring|subSequence,java.lang.Boolean,.*,java.lang.Byte,.*,java.lang.Character,.*,java.lang.Double,.*,java.lang.Float,.*,java.lang.Integer,.*,java.lang.Long,.*,java.lang.Math,.*,java.lang.Object,equals|hashCode|toString,java.lang.Short,.*,java.lang.StrictMath,.*,java.lang.String,.*,java.lang.Thread,interrupted,java.math.BigDecimal,.*,java.math.BigInteger,.*,java.net.InetAddress,.*,java.net.URI,.*,java.nio.channels.AsynchronousChannelGroup,.*,java.util.Arrays,.*,java.util.Collections,(?!addAll).*,java.util.List,of,java.util.Map,of|ofEntries|entry,java.util.Set,of,java.util.UUID,.*,java.util.concurrent.BlockingQueue,offer|remove,java.util.concurrent.CountDownLatch,await|getCount,java.util.concurrent.ExecutorService,awaitTermination|isShutdown|isTerminated,java.util.concurrent.ForkJoinPool,awaitQuiescence,java.util.concurrent.Semaphore,tryAcquire|availablePermits|isFair|hasQueuedThreads|getQueueLength|getQueuedThreads,java.util.concurrent.locks.Condition,await|awaitNanos|awaitUntil,java.util.concurrent.locks.Lock,tryLock|newCondition,java.util.regex.Matcher,pattern|toMatchResult|start|end|group|groupCount|matches|find|lookingAt|quoteReplacement|replaceAll|replaceFirst|regionStart|regionEnd|hasTransparentBounds|hasAnchoringBounds|hitEnd|requireEnd,java.util.regex.Pattern,.*,java.util.stream.BaseStream,.*,java.util.stream.DoubleStream,.*,java.util.stream.IntStream,.*,java.util.stream.LongStream,.*,java.util.stream.Stream,.*" />
+    </inspection_tool>
+    <inspection_tool class="IgnoredJUnitTest" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IllegalDependencyOnInternalPackage" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="IllegalIdentifier" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ImplicitArrayToString" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ImplicitCallToSuper" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreForObjectSubclasses" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ImplicitDefaultCharsetUsage" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ImplicitNullableNothingType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ImplicitNumericConversion" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreWideningConversions" value="false" />
+      <option name="ignoreCharConversions" value="false" />
+      <option name="ignoreConstantConversions" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ImplicitSubclassInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ImplicitThis" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ImplicitTypeConversion" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="BITS" value="1720" />
+      <option name="FLAG_EXPLICIT_CONVERSION" value="true" />
+      <option name="IGNORE_NODESET_TO_BOOLEAN_VIA_STRING" value="true" />
+    </inspection_tool>
+    <inspection_tool class="IncompatibleMask" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IncompatibleMaskJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IncompleteDestructuring" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IncompleteProperty" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="InconsistentCommentForJavaParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InconsistentLanguageLevel" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InconsistentLineSeparators" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InconsistentResourceBundle" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="InconsistentTextBlockIndent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IncorrectFormatting" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="IncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IncorrectOnMessageMethodsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="IncorrectParentDisposable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IncrementDecrementResultUsedJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IncrementDecrementUsedAsExpression" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IndexOfReplaceableByContains" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IndexZeroUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InfiniteLoopJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InfiniteLoopStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InfiniteRecursion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InfiniteRecursionJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InjectedReferences" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="InjectionNotApplicable" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="InjectionValueTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="InlineClassDeprecatedMigration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InnerClassMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InnerClassOnInterface" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreInnerInterfaces" value="false" />
+    </inspection_tool>
+    <inspection_tool class="InnerClassReferencedViaSubclass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InnerClassVariableHidesOuterClassVariable" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreInvisibleFields" value="true" />
+    </inspection_tool>
+    <inspection_tool class="InnerHTMLJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InsertLiteralUnderscores" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="InspectionDescriptionNotFoundInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InspectionMappingConsistency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InspectionUniqueToolbarId" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InspectionUsingGrayColors" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InstanceGuardedByStatic" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InstanceVariableInitialization" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignorePrimitives" value="false" />
+    </inspection_tool>
+    <inspection_tool class="InstanceVariableUninitializedUse" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignorePrimitives" value="false" />
+      <option name="annotationNamesString" value="" />
+    </inspection_tool>
+    <inspection_tool class="InstanceofCatchParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InstanceofChain" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreInstanceofOnLibraryClasses" value="false" />
+    </inspection_tool>
+    <inspection_tool class="InstanceofIncompatibleInterface" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InstanceofThis" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InstantiatingObjectToGetClassObject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InstantiationOfUtilityClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IntLiteralMayBeLongLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IntegerDivisionInFloatingPointContext" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IntegerMultiplicationImplicitCastToLong" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreNonOverflowingCompileTimeConstants" value="true" />
+    </inspection_tool>
+    <inspection_tool class="IntentionDescriptionNotFoundInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InterceptionAnnotationWithoutRuntimeRetention" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InterfaceMayBeAnnotatedFunctional" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="InterfaceMethodClashesWithObject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InterfaceNeverImplemented" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreInterfacesThatOnlyDeclareConstants" value="false" />
+    </inspection_tool>
+    <inspection_tool class="InterfaceWithOnlyOneDirectInheritor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="IntroduceWhenSubject" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="InvalidComparatorMethodReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InvalidImplementedBy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InvalidPropertyKeyForm" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InvalidProvidedBy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InvalidRequestParameters" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IterableUsedAsVararg" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IteratorHasNextCallsIteratorNext" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="IteratorNextDoesNotThrowNoSuchElementException" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JBoss" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JCenterRepository" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JDBCExecuteWithNonConstantString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JDBCPrepareStatementWithNonConstantString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JDBCResource" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="insideTryAllowed" value="false" />
+    </inspection_tool>
+    <inspection_tool class="JNDIResource" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="insideTryAllowed" value="false" />
+    </inspection_tool>
+    <inspection_tool class="JSAccessibilityCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSAnnotator" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JSArrowFunctionBracesCanBeRemoved" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSAssignmentUsedAsCondition" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSBitwiseOperatorUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSCheckFunctionSignatures" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSClassNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSClosureCompilerSyntax" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSCommentMatchesSignature" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSComparisonWithNaN" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSConsecutiveCommasInArrayLiteral" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSConstantReassignment" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JSConstructorReturnsPrimitive" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSDeclarationsAtScopeStart" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSDeprecatedSymbols" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSDuplicateCaseLabel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSDuplicatedDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSEqualityComparisonWithCoercion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSEqualityComparisonWithCoercion.TS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSFileReferences" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSFunctionExpressionToArrowFunction" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSHint" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="JSIgnoredPromiseFromCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSIncompatibleTypesComparison" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSJQueryEfficiency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSJoinVariableDeclarationAndAssignment" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSLastCommaInArrayLiteral" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSLastCommaInObjectLiteral" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSMethodCanBeStatic" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSMismatchedCollectionQueryUpdate" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="queries" value="trace,write,forEach,length,size" />
+      <option name="updates" value="pop,push,shift,splice,unshift,add,insert,remove,reverse,copyWithin,fill,sort" />
+    </inspection_tool>
+    <inspection_tool class="JSMissingSwitchBranches" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSMissingSwitchDefault" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSNonASCIINames" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSNonStrictModeUsed" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSObjectNullOrUndefined" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSOctalInteger" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JSPotentiallyInvalidConstructorUsage" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="myConsiderUppercaseFunctionsToBeConstructors" value="true" />
+    </inspection_tool>
+    <inspection_tool class="JSPotentiallyInvalidTargetOfIndexedPropertyAccess" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSPotentiallyInvalidUsageOfClassThis" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSPotentiallyInvalidUsageOfThis" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSPrimitiveTypeWrapperUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSRedundantSwitchStatement" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSReferencingMutableVariableFromClosure" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSRemoveUnnecessaryParentheses" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSStringConcatenationToES6Template" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSSuspiciousEqPlus" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSSuspiciousNameCombination" enabled="true" level="WARNING" enabled_by_default="true">
+      <group names="x,width,left,right" />
+      <group names="y,height,top,bottom" />
+      <exclude classes="Math" />
+    </inspection_tool>
+    <inspection_tool class="JSSwitchVariableDeclarationIssue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSTestFailedLine" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSTypeOfValues" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUndeclaredVariable" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUndefinedPropertyAssignment" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnfilteredForInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSUnnecessarySemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnreachableSwitchBranches" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnresolvedExtXType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnresolvedFunction" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnresolvedLibraryURL" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnresolvedReactComponent" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnresolvedVariable" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnusedAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnusedGlobalSymbols" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUnusedLocalSymbols" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSUrlImportUsage" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JSValidateJSDoc" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSValidateTypes" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSVoidFunctionReturnValueUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSXNamespaceValidation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSXSyntaxUsed" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="JUnit3StyleTestMethodInJUnit4Class" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JUnit4AnnotatedMethodInJUnit3TestCase" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JUnit5AssertionsConverter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JUnit5Converter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JUnitMalformedDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JUnitTestNG" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Java8CollectionRemoveIf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8ListReplaceAll" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8ListSort" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8MapApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8MapForEach" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java9CollectionFactory" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java9ModuleExportsPackageToItself" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java9RedundantRequiresStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java9ReflectionClassVisibility" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java9UndeclaredServiceUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaCollectionsStaticMethod" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaCollectionsStaticMethodOnImmutableList" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxColorRgb" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxDefaultTag" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxEventHandler" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxRedundantPropertyValue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxResourcePropertyValue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxUnresolvedFxIdReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxUnresolvedStyleClassReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaFxUnusedImports" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaLangImport" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JavaLangInvokeHandleSignature" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaMapForEach" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaModuleNaming" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaReflectionInvocation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaReflectionMemberAccess" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaRequiresAutoModule" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavaStylePropertiesInvocation" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JavacQuirks" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavadocBlankLines" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavadocDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavadocHtmlLint" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="JavadocLinkAsPlainText" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JavadocReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JavaeeApplicationDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JdkProxiedBeanTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JmhInspections" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JoinDeclarationAndAssignment" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JoinDeclarationAndAssignmentJava" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="JpaAttributeMemberSignatureInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaAttributeTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaConfigDomFacetInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JpaDataSourceORMDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaDataSourceORMInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaEntityGraphsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaEntityListenerInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaEntityListenerWarningsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JpaMissingIdInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaModelReferenceInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaORMDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaObjectClassSignatureInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaQlInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JpaQueryApiInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="Json5StandardCompliance" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JsonDuplicatePropertyKeys" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonPathEvaluateUnknownKey" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonPathUnknownFunction" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonPathUnknownOperator" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonSchemaCompliance" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonSchemaDeprecation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonSchemaRefReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JsonStandardCompliance" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JspAbsolutePathInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JspDirectiveInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JspPropertiesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JspTagBodyContent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JspUnescapedEl" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Junit4Converter" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="KDocMissingDocumentation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="KDocUnresolvedReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KeySetIterationMayUseEntrySet" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="KotlinCatchMayIgnoreException" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinConstantConditions" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinCovariantEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinDeprecation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinDoubleNegation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinEqualsBetweenInconvertibleTypes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinInternalInJava" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="KotlinInvalidBundleOrProperty" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="KotlinJvmAnnotationInJava" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinLoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="KotlinMavenPluginPhase" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinPlaceholderCountMatchesArgumentCount" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinRedundantDiagnosticSuppress" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinRedundantOverride" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinSealedInheritorsInJava" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="KotlinTestJUnit" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinThrowableNotThrown" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="KotlinUnusedImport" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LabeledStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LabeledStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LambdaBodyCanBeCodeBlock" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="LambdaCanBeMethodCall" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="LambdaCanBeReplacedWithAnonymous" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="LambdaParameterHidingMemberVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LambdaParameterNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LambdaParameterTypeCanBeSpecified" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="LambdaUnfriendlyMethodOverload" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LanguageDetectionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LanguageMismatch" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="CHECK_NON_ANNOTATED_REFERENCES" value="true" />
+    </inspection_tool>
+    <inspection_tool class="LateinitVarOverridesLateinitVar" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LawOfDemeter" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreLibraryCalls" value="true" />
+    </inspection_tool>
+    <inspection_tool class="LeakableMapKey" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LeakingThis" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LengthOneStringInIndexOf" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LengthOneStringsInConcatenation" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="LessResolvedByNameOnly" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="LessUnresolvedMixin" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LessUnresolvedVariable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LiftReturnOrAssignment" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="LimitedScopeInnerClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ListIndexOfReplaceableByContains" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ListRemoveInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ListenerMayUseAdapter" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="checkForEmptyMethods" value="true" />
+    </inspection_tool>
+    <inspection_tool class="LiteralAsArgToStringEquals" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LoadLibraryWithNonConstantString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LocalCanBeFinal" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="REPORT_VARIABLES" value="true" />
+      <option name="REPORT_PARAMETERS" value="true" />
+    </inspection_tool>
+    <inspection_tool class="LocalVariableHidingMemberVariable" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreInvisibleFields" value="true" />
+      <option name="m_ignoreStaticMethods" value="true" />
+    </inspection_tool>
+    <inspection_tool class="LocalVariableName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="LocalVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreForLoopParameters" value="false" />
+      <option name="m_ignoreCatchParameters" value="false" />
+      <option name="m_regex" value="[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="1" />
+      <option name="m_maxLength" value="20" />
+    </inspection_tool>
+    <inspection_tool class="LocalVariableNamingConventionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z]*" />
+      <option name="m_minLength" value="1" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="LogStatementGuardedByLogCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
+    </inspection_tool>
+    <inspection_tool class="LoggingConditionDisagreesWithLogStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Lombok" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LongLine" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LongLiteralsEndingWithLowercaseL" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LoopConditionNotUpdatedInsideLoop" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreIterators" value="false" />
+    </inspection_tool>
+    <inspection_tool class="LoopStatementThatDoesntLoopJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LoopStatementsThatDontLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LoopToCallChain" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="LoopWithImplicitTerminationCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LossyEncoding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MVCPathVariableInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MagicCharacter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MagicConstant" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MagicNumber" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MagicNumberJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MainFunctionReturnUnit" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MalformedDataProvider" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MalformedFormatString" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ManualArrayCopy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ManualArrayToCollectionCopy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ManualMinMaxCalculation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MapGetWithNotNullAssertionOperator" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="MapReplaceableByEnumMap" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MarkdownIncorrectTableFormatting" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MarkdownIncorrectlyNumberedListItem" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MarkdownNoTableBorders" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MarkdownUnresolvedFileReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MarkedForRemoval" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MarkerInterface" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MaskedAssertion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MathRandomCastToInt" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MavenCoroutinesDeprecation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MavenDuplicateDependenciesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MavenDuplicatePluginInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MavenModelInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MavenPackageUpdate" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MavenPackageVersionRange" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MavenParentMissedVersionInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MavenPropertyInParent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MavenRedundantGroupId" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MayBeConstant" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MeaninglessRecordAnnotationInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MemberVisibilityCanBePrivate" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="MetaAnnotationWithoutRuntimeRetention" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MethodCallInLoopCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodCanBeVariableArityMethod" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="MethodCount" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="20" />
+      <option name="ignoreGettersAndSetters" value="false" />
+      <option name="ignoreOverridingMethods" value="false" />
+    </inspection_tool>
+    <inspection_tool class="MethodCoupling" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_includeJavaClasses" value="false" />
+      <option name="m_includeLibraryClasses" value="false" />
+      <option name="m_limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="MethodMayBeStatic" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_onlyPrivateOrFinal" value="false" />
+      <option name="m_ignoreEmptyMethods" value="true" />
+    </inspection_tool>
+    <inspection_tool class="MethodMayBeSynchronized" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodNameSameAsClassName" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MethodNameSameAsParentName" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodOnlyUsedFromInnerClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreMethodsAccessedFromAnonymousClass" value="false" />
+      <option name="ignoreStaticMethodsFromNonStaticInnerClass" value="false" />
+      <option name="onlyReportStaticMethods" value="false" />
+    </inspection_tool>
+    <inspection_tool class="MethodOverloadsParentMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodOverridesInaccessibleMethodOfSuper" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodOverridesStaticMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodRefCanBeReplacedWithLambda" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="MethodReturnAlwaysConstant" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodWithMultipleLoops" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MicronautDataMethodInconsistency" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MicronautDataRepositoryMethodParameters" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MicronautDataRepositoryMethodReturnType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MigrateAssertToMatcherAssert" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MigrateDiagnosticSuppression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MimeType" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MinMaxValuesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MismatchedArrayReadWrite" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MismatchedCollectionQueryUpdate" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="queryNames">
+        <value />
+      </option>
+      <option name="updateNames">
+        <value />
+      </option>
+      <option name="ignoredClasses">
+        <value />
+      </option>
+    </inspection_tool>
+    <inspection_tool class="MismatchedStringBuilderQueryUpdate" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MismatchedStringCase" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MisorderedAssertEqualsArguments" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MissingAccessibleContext" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissingActionUpdateThread" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissingAspectjAutoproxyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissingDeprecatedAnnotation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MissingDeprecatedAnnotationOnScheduledForRemovalApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MissingFinalNewline" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MissingJavadoc" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MissingMnemonic" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreObjectMethods" value="true" />
+      <option name="ignoreAnonymousClassMethods" value="false" />
+    </inspection_tool>
+    <inspection_tool class="MissingPackageInfo" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MissingRecentApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MissingSerialAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MissortedModifiers" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_requireAnnotationsFirst" value="true" />
+    </inspection_tool>
+    <inspection_tool class="MisspelledEquals" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MisspelledHeader" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MisspelledMethodName" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MnCacheAnnotationParameters" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MnPropertiesConfig" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MnUnresolvedPathVariable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MnYamlConfig" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ModuleWithTooFewClasses" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="ModuleWithTooManyClasses" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="100" />
+    </inspection_tool>
+    <inspection_tool class="MongoJSDeprecationInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MongoJSExtDeprecationInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MongoJSExtResolveInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MongoJSExtSideEffectsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MongoJSResolveInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MongoJSSideEffectsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MoveFieldAssignmentToInitializer" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="MoveLambdaOutsideParentheses" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MoveVariableDeclarationIntoWhen" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="MsBuiltinInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MsOrderByInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MultiCatchCanBeSplit" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="MultipleBindingAnnotations" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MultipleExceptionsDeclaredOnTestMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MultipleInjectedConstructorsForClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MultipleMethodDesignatorsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MultipleRepositoryUrls" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MultipleReturnPointsPerMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreGuardClauses" value="false" />
+      <option name="ignoreEqualsMethod" value="false" />
+      <option name="m_limit" value="1" />
+    </inspection_tool>
+    <inspection_tool class="MultipleTopLevelClassesInFile" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MultipleVariablesInDeclaration" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="MultiplyOrDivideByPowerOfTwo" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="checkDivision" value="false" />
+    </inspection_tool>
+    <inspection_tool class="MustAlreadyBeRemovedApi" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="MutinyCallingSubscribeInNonBlockingScope" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MysqlLoadDataPathInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MysqlParsingInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NakedNotify" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NativeMethods" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NegatedConditional" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreNegatedNullComparison" value="true" />
+    </inspection_tool>
+    <inspection_tool class="NegatedConditionalExpression" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NegatedConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NegatedEqualityExpression" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NegatedIfElse" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreNegatedNullComparison" value="true" />
+      <option name="m_ignoreNegatedZeroComparison" value="false" />
+    </inspection_tool>
+    <inspection_tool class="NegatedIfStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NegativelyNamedBooleanVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedAssignmentJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedConditionalExpression" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedFunctionCallJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedFunctionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_includeAnonymousFunctions" value="false" />
+    </inspection_tool>
+    <inspection_tool class="NestedLambdaShadowedImplicitParameter" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="NestedMethodCall" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreFieldInitializations" value="true" />
+    </inspection_tool>
+    <inspection_tool class="NestedSwitchStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedSwitchStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedSynchronizedStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestedTryStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NestingDepth" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="NestingDepthJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="NewClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NewExceptionWithoutArguments" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NewGroovyClassNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NewInstanceOfSingleton" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NewMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NewObjectEquality" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NewStringBufferWithCharArgument" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NoButtonGroup" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NoConstructorMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="NoExplicitFinalizeCalls" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NoLabelFor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NoScrollPane" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NodeCoreCodingAssistance" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NonAsciiCharacters" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NonAtomicOperationOnVolatileField" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NonBlockStatementBodyJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonBooleanMethodNameMayNotStartWithQuestion" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="questionString" value="are,can,check,contains,could,endsWith,equals,has,is,matches,must,shall,should,startsWith,was,were,will,would" />
+      <option name="ignoreBooleanMethods" value="false" />
+      <option name="onlyWarnOnBaseMethods" value="true" />
+    </inspection_tool>
+    <inspection_tool class="NonCommentSourceStatements" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="30" />
+    </inspection_tool>
+    <inspection_tool class="NonDefaultConstructor" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="NonExceptionNameEndsWithException" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonExhaustiveWhenStatementMigration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonExtendableApiUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NonFinalClone" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonFinalFieldInEnum" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NonFinalFieldInImmutable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonFinalFieldOfException" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonFinalGuard" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonFinalStaticVariableUsedInClassInitialization" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonFinalUtilityClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonProtectedConstructorInAbstractClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreNonPublicClasses" value="false" />
+    </inspection_tool>
+    <inspection_tool class="NonPublicClone" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonReproducibleMathCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonSerializableFieldInSerializableClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignorableAnnotations">
+        <value />
+      </option>
+      <option name="ignoreAnonymousInnerClasses" value="false" />
+      <option name="superClassString" value="java.awt.Component" />
+    </inspection_tool>
+    <inspection_tool class="NonSerializableObjectBoundToHttpSession" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonSerializableObjectPassedToObjectStream" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonSerializableWithSerialVersionUIDField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonSerializableWithSerializationMethods" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonShortCircuitBoolean" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonStaticFinalLogger" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerClassName" value="java.util.logging.Logger,org.slf4j.Logger,org.apache.commons.logging.Log,org.apache.log4j.Logger,org.apache.logging.log4j.Logger" />
+    </inspection_tool>
+    <inspection_tool class="NonStrictComparisonCanBeEquality" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="NonSynchronizedMethodOverridesSynchronizedMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NonThreadSafeLazyInitialization" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NoopMethodInAbstractClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NotNullFieldNotInitialized" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NotifyCalledOnCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NotifyWithoutCorrespondingWait" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NpmUsedModulesInstalled" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="NullArgumentToVariableArgMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NullChecksToSafeCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="NullThrown" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="NullableBooleanElvis" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="NullableProblems" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL" value="true" />
+      <option name="REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL" value="true" />
+      <option name="REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE" value="true" />
+      <option name="REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL" value="true" />
+      <option name="REPORT_NOT_ANNOTATED_GETTER" value="true" />
+      <option name="REPORT_NOT_ANNOTATED_SETTER_PARAMETER" value="true" />
+      <option name="REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS" value="true" />
+      <option name="REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD" value="true" />
+    </inspection_tool>
+    <inspection_tool class="NumberEquality" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NumericOverflow" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="NumericToString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ObjectAllocationIgnoredJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ObjectAllocationInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ObjectEquality" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="m_ignoreEnums" value="true" />
+      <option name="m_ignoreClassObjects" value="true" />
+      <option name="m_ignorePrivateConstructors" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ObjectEqualsCanBeEquality" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ObjectInstantiationInEqualsHashCode" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ObjectLiteralToLambda" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ObjectNotify" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ObjectPropertyName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ObjectToString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ObjectsEqualsCanBeSimplified" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ObsoleteCollection" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreRequiredObsoleteCollectionTypes" value="true" />
+    </inspection_tool>
+    <inspection_tool class="ObsoleteExperimentalCoroutines" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ObsoleteKotlinJsPackages" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ObviousNullCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OctalAndDecimalIntegersMixed" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OctalLiteral" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OnDemandImport" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OneButtonGroup" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalAssignedToNull" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalContainsCollection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OptionalExpectation" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="OptionalGetWithoutIsPresent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalIsPresent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalToIf" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="OptionalUsedAsFieldOrParameterType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OraMissingBodyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OraOverloadInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OraUnmatchedForwardDeclarationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="OverflowingLoopIndex" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OverloadedMethodsWithSameNumberOfParameters" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreInconvertibleTypes" value="true" />
+    </inspection_tool>
+    <inspection_tool class="OverloadedVarargsMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OverlyComplexArithmeticExpression" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="6" />
+    </inspection_tool>
+    <inspection_tool class="OverlyComplexArithmeticExpressionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="6" />
+    </inspection_tool>
+    <inspection_tool class="OverlyComplexBooleanExpression" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+      <option name="m_ignorePureConjunctionsDisjunctions" value="true" />
+    </inspection_tool>
+    <inspection_tool class="OverlyComplexBooleanExpressionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="OverlyLargePrimitiveArrayInitializer" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="64" />
+    </inspection_tool>
+    <inspection_tool class="OverlyLongLambda" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OverlyStrongTypeCast" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreInMatchingInstanceof" value="false" />
+    </inspection_tool>
+    <inspection_tool class="OverridableMethodCallDuringObjectConstruction" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OverriddenMethodCallDuringObjectConstruction" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="OverrideDeprecatedMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="OverrideOnly" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OverwrittenKey" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PackageDirectoryMismatch" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="PackageDotHtmlMayBePackageInfo" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PackageInMultipleModules" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PackageInfoWithoutPackage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PackageJsonMismatchedDependency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PackageName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="PackageNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z]*" />
+      <option name="m_minLength" value="3" />
+      <option name="m_maxLength" value="16" />
+    </inspection_tool>
+    <inspection_tool class="PackageVisibleField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PackageVisibleInnerClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreEnums" value="false" />
+      <option name="ignoreInterfaces" value="false" />
+    </inspection_tool>
+    <inspection_tool class="PackageWithTooFewClasses" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="PackageWithTooManyClasses" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="limit" value="50" />
+    </inspection_tool>
+    <inspection_tool class="ParameterCanBeLocal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ParameterHidingMemberVariable" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreInvisibleFields" value="true" />
+      <option name="m_ignoreStaticMethodParametersHidingInstanceFields" value="true" />
+      <option name="m_ignoreForConstructors" value="false" />
+      <option name="m_ignoreForPropertySetters" value="false" />
+      <option name="m_ignoreForAbstractMethods" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ParameterNameDiffersFromOverriddenParameter" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreSingleCharacterNames" value="false" />
+      <option name="m_ignoreOverridesOfLibraryMethods" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ParameterNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z\d]*" />
+      <option name="m_minLength" value="1" />
+      <option name="m_maxLength" value="20" />
+    </inspection_tool>
+    <inspection_tool class="ParameterNamingConventionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_regex" value="[a-z][A-Za-z]*" />
+      <option name="m_minLength" value="1" />
+      <option name="m_maxLength" value="32" />
+    </inspection_tool>
+    <inspection_tool class="ParameterTypePreventsOverriding" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ParameterizedParametersStaticCollection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ParametersPerConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ParametersPerFunctionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="ParametersPerMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="5" />
+    </inspection_tool>
+    <inspection_tool class="PathAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PatternNotApplicable" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PatternOverriddenByNonAnnotatedMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PatternValidation" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="CHECK_NON_CONSTANT_VALUES" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PatternVariableCanBeUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PatternVariableHidesField" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PbDuplicatedImports" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PgSelectFromProcedureInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PlaceholderCountMatchesArgumentCount" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PlatformDetectionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PlatformExtensionReceiverOfInline" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PluginXmlCapitalization" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PluginXmlDynamicPlugin" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PluginXmlI18n" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PluginXmlValidity" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PointcutMethodStyleInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PointlessArithmeticExpression" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreExpressionsContainingConstants" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PointlessArithmeticExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PointlessBinding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PointlessBitwiseExpression" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreExpressionsContainingConstants" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PointlessBitwiseExpressionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreExpressionsContainingConstants" value="false" />
+    </inspection_tool>
+    <inspection_tool class="PointlessBooleanExpression" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreExpressionsContainingConstants" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PointlessBooleanExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PointlessIndexOfComparison" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PointlessNullCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PostfixTemplateDescriptionNotFound" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PresentationAnnotation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PreviewFeature" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PrimitiveArrayArgumentToVariableArgMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PrivatePropertyName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ProblematicVarargsMethodOverride" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ProblematicWhitespace" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ProhibitJvmOverloadsOnConstructorsOfAnnotationClassesMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="ProhibitRepeatedUseSiteTargetAnnotationsMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="ProhibitTypeParametersForLocalVariablesMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="ProhibitUseSiteTargetAnnotationsOnSuperTypesMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="PropertyName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="PropertyValueSetToItself" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ProtectedField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ProtectedInFinal" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ProtectedInnerClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreEnums" value="false" />
+      <option name="ignoreInterfaces" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ProtectedMemberInFinalClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PsiElementConcatenation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="PublicApiImplicitType" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="PublicConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PublicConstructorInNonPublicClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PublicField" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreEnums" value="false" />
+      <option name="ignorableAnnotations">
+        <value />
+      </option>
+    </inspection_tool>
+    <inspection_tool class="PublicFieldAccessedInSynchronizedContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PublicInnerClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreEnums" value="false" />
+      <option name="ignoreInterfaces" value="false" />
+    </inspection_tool>
+    <inspection_tool class="PublicMethodNotExposedInInterface" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignorableAnnotations">
+        <value />
+      </option>
+      <option name="onlyWarnIfContainingClassImplementsAnInterface" value="false" />
+    </inspection_tool>
+    <inspection_tool class="PublicMethodWithoutLogging" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerClassName" value="java.util.logging.Logger,org.slf4j.Logger,org.apache.commons.logging.Log,org.apache.log4j.Logger,org.apache.logging.log4j.Logger" />
+    </inspection_tool>
+    <inspection_tool class="PublicStaticArrayField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PublicStaticCollectionField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="QsPrivateBeanMembersInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="QsProperties" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="QsUndeclaredPathMimeTypesInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="QsYaml" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="QuestionableName" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="nameString" value="aa,abc,bad,bar,bar2,baz,baz1,baz2,baz3,bb,blah,bogus,bool,cc,dd,defau1t,dummy,dummy2,ee,fa1se,ff,foo,foo1,foo2,foo3,foobar,four,fred,fred1,fred2,gg,hh,hello,hello1,hello2,hello3,ii,nu11,one,silly,silly2,string,two,that,then,three,whi1e,var" />
+    </inspection_tool>
+    <inspection_tool class="QuickFixGetFamilyNameViolation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="R8IgnoredFlags" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RandomDoubleForRandomInteger" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RawUseOfParameterizedType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactiveStreamsNullableInLambdaInTransform" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactiveStreamsPublisherImplementation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactiveStreamsSubscriberImplementation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactiveStreamsThrowInOperator" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactiveStreamsTooLongSameOperatorsChain" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactiveStreamsUnusedPublisher" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReactorAutomaticDebugger" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReadObjectAndWriteObjectPrivate" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReadObjectInitialization" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReadResolveAndWriteReplaceProtected" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReadWriteStringCanBeUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReassignedToPlainText" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReassignedVariable" enabled="true" level="TEXT ATTRIBUTES" enabled_by_default="true" />
+    <inspection_tool class="RecordCanBeClass" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RecordStoreResource" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RecursiveEqualsCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RecursivePropertyAccessor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantArrayCreation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantAsSequence" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantAsync" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantCast" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantClassCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantCollectionOperation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantCompanionReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantComparatorComparing" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantCompareCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantElseInIf" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RedundantElvisReturnNull" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantEmptyInitializerBlock" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="RedundantEnumConstructorInvocation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantExplicitClose" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantExplicitType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantExplicitVariableType" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RedundantFieldInitialization" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RedundantFileCreation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantGetter" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantIf" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantImplements" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreSerializable" value="false" />
+      <option name="ignoreCloneable" value="false" />
+    </inspection_tool>
+    <inspection_tool class="RedundantInnerClassModifier" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RedundantLabelMigration" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="RedundantLabeledSwitchRuleCodeBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantLambdaArrow" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantLambdaOrAnonymousFunction" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantLambdaParameterType" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RedundantMethodOverride" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RedundantModalityModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantModifiersUtilityClassLombok" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RedundantModifiersValLombok" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantModifiersValueLombok" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantNotNullExtensionReceiverOfInline" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="RedundantNullableReturnType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantObjectTypeCheck" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RedundantOperationOnEmptyContainer" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantRecordConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantRequireNotNullCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantReturnLabel" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantRunCatching" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantSamConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantScheduledForRemovalAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantScopeBinding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantSemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantSetter" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantSlf4jDefinition" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantStreamOptionalCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantStringFormatCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantSuppression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantSuspendModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantThrows" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantToBinding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantToProviderBinding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantTypeArguments" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantTypeConversion" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="CHECK_ANY" value="false" />
+    </inspection_tool>
+    <inspection_tool class="RedundantUnitExpression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantUnitReturnType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantUnmodifiable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantVisibilityModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantWith" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReferencesToClassesFromDefaultPackagesInJSPFile" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ReflectionForUnavailableAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RefusedBequest" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreEmptySuperMethods" value="false" />
+      <option name="onlyReportWhenAnnotated" value="true" />
+    </inspection_tool>
+    <inspection_tool class="RegExpAnonymousGroup" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RegExpDuplicateAlternationBranch" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpDuplicateCharacterInClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpEmptyAlternationBranch" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpEscapedMetaCharacter" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RegExpOctalEscape" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RegExpRedundantClassElement" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpRedundantEscape" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpRedundantNestedCharacterClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpRepeatedSpace" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpSimplifiable" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpSingleCharAlternation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpSuspiciousBackref" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpUnexpectedAnchor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RegExpUnnecessaryNonCapturingGroup" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveCurlyBracesFromTemplate" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveEmptyClassBody" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="RemoveEmptyParenthesesFromAnnotationEntry" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveEmptyParenthesesFromLambdaCall" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="RemoveEmptyPrimaryConstructor" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveEmptySecondaryConstructorBody" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveExplicitSuperQualifier" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveExplicitTypeArguments" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveForLoopIndices" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveLiteralUnderscores" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="RemoveRedundantBackticks" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveRedundantCallsOfConversionMethods" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveRedundantQualifierName" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveRedundantSpreadOperator" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveSetterParameterType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveSingleExpressionStringTemplate" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveToStringInStringTemplate" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceAllDot" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceArrayEqualityOpWithArraysEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceArrayOfWithLiteral" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceAssertBooleanWithAssertEquality" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceAssignmentWithOperatorAssignment" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreLazyOperators" value="true" />
+      <option name="ignoreObscureOperators" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ReplaceAssignmentWithOperatorAssignmentJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReplaceAssociateFunction" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceCallWithBinaryOperator" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceCollectionCountWithSize" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReplaceGetOrSet" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ReplaceGuardClauseWithFunctionCall" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceInefficientStreamCount" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceIsEmptyWithIfEmpty" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceJavaStaticMethodWithKotlinAnalog" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceManualRangeWithIndicesCalls" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ReplaceMapIndexedWithListGenerator" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceNegatedIsEmptyWithIsNotEmpty" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceNotNullAssertionWithElvisReturn" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReplaceNullCheck" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceOnLiteralHasNoEffect" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplacePutWithAssignment" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceRangeStartEndInclusiveWithFirstLast" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceRangeToWithUntil" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSizeCheckWithIsNotEmpty" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSizeZeroCheckWithIsEmpty" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceStringFormatWithLiteral" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSubstringWithDropLast" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSubstringWithIndexingOperation" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSubstringWithSubstringAfter" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSubstringWithSubstringBefore" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSubstringWithTake" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceToStringWithStringTemplate" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceToWithInfixForm" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceWithEnumMap" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceWithIgnoreCaseEquals" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceWithImportAlias" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceWithJavadoc" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReplaceWithOperatorAssignment" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RequiredAttributes" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="myAdditionalRequiredHtmlAttributes" value="" />
+    </inspection_tool>
+    <inspection_tool class="RequiredBeanTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ReservedWordUsedAsNameJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RestParamTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="RestResourceMethodInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="RestWrongDefaultValueInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="RestrictReturnStatementTargetMigration" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="ResultOfObjectAllocationIgnored" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ResultSetIndexZero" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReturnFromFinallyBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReturnFromFinallyBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReturnNull" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_reportObjectMethods" value="true" />
+      <option name="m_reportArrayMethods" value="true" />
+      <option name="m_reportCollectionMethods" value="true" />
+      <option name="m_ignorePrivateMethods" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ReturnOfInnerClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReturnSeparatedFromComputation" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="ReturnThis" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReuseOfLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReuseOfLocalVariableJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RuntimeExec" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RuntimeExecWithNonConstantString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SSBasedInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SafeCastWithReturn" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SafeLock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SafeVarargsDetector" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SamePackageImport" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SameParameterValue" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
+    <inspection_tool class="SameReturnValue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SassScssResolvedByNameOnly" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SassScssUnresolvedMixin" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SassScssUnresolvedPlaceholderSelector" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SassScssUnresolvedVariable" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ScheduledMethodInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ScheduledThreadPoolExecutorWithZeroCoreThreads" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ScopeFunctionConversion" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="SecondUnsafeCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SecurityRoles" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SelfAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SelfIncludingJspFiles" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SelfReferenceConstructorParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SerialAnnotationUsedOnWrongMember" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SerialPersistentFieldsWithWrongSignature" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SerialVersionUIDNotStaticFinal" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SerializableCtor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SerializableDeserializableClassInSecureContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SerializableHasSerialVersionUIDField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SerializableHasSerializationMethods" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreAnonymousInnerClasses" value="false" />
+      <option name="superClassString" value="java.io.Externalizable,java.awt.Component" />
+    </inspection_tool>
+    <inspection_tool class="SerializableInnerClassHasSerialVersionUIDField" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreAnonymousInnerClasses" value="false" />
+      <option name="superClassString" value="java.awt.Component" />
+    </inspection_tool>
+    <inspection_tool class="SerializableInnerClassWithNonSerializableOuterClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreAnonymousInnerClasses" value="false" />
+      <option name="superClassString" value="java.awt.Component" />
+    </inspection_tool>
+    <inspection_tool class="SerializableRecordContainsIgnoredMembers" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SerializableStoresNonSerializable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SerializableWithUnconstructableAncestor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ServerEndpointInconsistencyInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ServletWithoutMappingInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SessionScopedInjectsRequestScoped" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SetReplaceableByEnumSet" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SetterBackingFieldAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SharedThreadLocalRandom" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ShellCheck" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ShiftOutOfRange" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ShiftOutOfRangeJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ShouldBeWrappedInCondition" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ShrinkerArrayType" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ShrinkerInnerClassSeparator" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ShrinkerInvalidFlags" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ShrinkerUnresolvedReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SignalWithoutCorrespondingAwait" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SillyAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SillyAssignmentJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimpleDateFormatWithoutLocale" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SimpleRedundantLet" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifiableAnnotation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SimplifiableAssertion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifiableBooleanExpression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifiableCall" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifiableCallChain" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifiableConditionalExpression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifiableEqualsExpression" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SimplifiableIfStatement" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="SimplifyAssertNotNull" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="SimplifyBooleanWithConstants" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifyCollector" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifyForEach" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="SimplifyNegatedBinaryExpression" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifyNestedEachInScopeFunction" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifyOptionalCallChains" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifyStreamApiCallChains" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SimplifyWhenWithBooleanConstantCondition" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="Since15" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SingleCharacterStartsWith" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SingleClassImport" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SingleElementAnnotation" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="SingleStatementInBlock" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="Singleton" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SingletonConstructor" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SingletonInjectsScoped" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SizeReplaceableByIsEmpty" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SleepWhileHoldingLock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SlowAbstractSetRemoveAll" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SlowListContainsAll" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SmallRyeConfigMappingMissingPrefixInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SocketResource" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="insideTryAllowed" value="false" />
+    </inspection_tool>
+    <inspection_tool class="SortModifiers" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SortedCollectionWithNonComparableKeys" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SourceToSinkFlow" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="true">
+      <option name="processCode" value="true" />
+      <option name="processLiterals" value="true" />
+      <option name="processComments" value="true" />
+    </inspection_tool>
+    <inspection_tool class="SpringAopErrorsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringAopPointcutExpressionInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringAopWarningsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringBeanAttributesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringBeanConstructorArgInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringBeanInstantiationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringBeanLookupMethodInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringBeanNameConventionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringBootAdditionalConfig" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringBootApplicationProperties" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringBootApplicationSetup" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringBootApplicationYaml" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringBootBootstrapConfigurationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringBootReactorHooksOnDebug" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringCacheAnnotationsOnInterfaceInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringCacheNamesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringCacheableAndCachePutInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringCacheableComponentsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringCloudStreamInconsistencyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringCloudStreamMessageChannelInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringComponentScan" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringConfigurationProxyMethods" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringContextConfigurationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringDataMethodInconsistencyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringDataRepositoryMethodParametersInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringDataRepositoryMethodReturnTypeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringDependsOnUnresolvedBeanInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringElInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringElStaticFieldInjectionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringEventListenerInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringFacetCodeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringFacetInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="checkTestFiles" value="false" />
+    </inspection_tool>
+    <inspection_tool class="SpringFacetProgrammaticInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringFactoryMethodInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringHandlersSchemasHighlighting" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringImportResource" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringInactiveProfileHighlightingInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringIncorrectResourceTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringInjectionValueConsistencyInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringInjectionValueStyleInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringIntegrationDeprecations21" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringIntegrationMethodEndpointInconsistency" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringIntegrationModel" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringJavaAutowiredFieldsWarningInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringJavaAutowiredMembersInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringJavaConstructorAutowiringInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringJavaInjectionPointsAutowiringInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringJavaStaticMembersAutowiringInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringLookupInjectionInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringMVCInitBinder" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringMVCViewInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringPlaceholdersInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringProfileExpression" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringPropertySource" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringPublicFactoryMethodInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringQualifierCopyableLombok" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringRequiredAnnotationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringRequiredPropertyInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringScopesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringSecurityAnnotationBeanPointersResolveInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringSecurityDebugActivatedInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringSecurityModelInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringShellCommandInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringShellReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringTestingDirtiesContextInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringTestingSqlInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringTestingTransactionalInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringTransactionalComponentInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringWebSocketConfigurationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringXmlAutowireExplicitlyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SpringXmlAutowiringInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SpringXmlModelInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SqlAddNotNullColumnInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlAggregatesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlAmbiguousColumnInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlCallNotationInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SqlCaseVsCoalesceInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlCaseVsIfInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlCheckUsingColumnsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlConstantConditionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlConstantExpressionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlCurrentSchemaInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlDeprecateTypeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlDerivedTableAliasInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlDialectInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlDropIndexedColumnInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlDtInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlDuplicateColumnInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlGotoInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SqlIdentifierInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlIllegalCursorStateInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlInsertIntoGeneratedColumnInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlInsertNullIntoNotNullInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlInsertValuesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlJoinWithoutOnInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlMisleadingReferenceInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlMissingColumnAliasesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SqlMissingReturnInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SqlMultipleLimitClausesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlNamedArgumentsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SqlNoDataSourceInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlNullComparisonInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlRedundantAliasInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlRedundantCodeInCoalesceInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlRedundantElseNullInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlRedundantLimitInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlRedundantOrderingDirectionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlResolveInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SqlShadowingAliasInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlShouldBeInGroupByInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlSideEffectsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlSignatureInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlStorageInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlStringLengthExceededInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlTransactionStatementInTriggerInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlTriggerTransitionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlTypeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlUnicodeStringLiteralInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlUnreachableCodeInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlUnusedCteInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlUnusedSubqueryItemInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlUnusedVariableInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SqlWithoutWhereInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StandardJS" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="StandardVariableNames" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StatefulEp" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StatementsPerFunctionJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="30" />
+    </inspection_tool>
+    <inspection_tool class="StaticCallOnSubclass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticCollection" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreWeakCollections" value="false" />
+    </inspection_tool>
+    <inspection_tool class="StaticFieldReferenceOnSubclass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticGuardedByInstance" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticImport" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticInheritance" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticInitializerReferencesSubClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StaticMethodOnlyUsedInOneClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticNonFinalField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StaticPseudoFunctionalStyleMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StaticVariableInitialization" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignorePrimitives" value="false" />
+    </inspection_tool>
+    <inspection_tool class="StaticVariableUninitializedUse" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignorePrimitives" value="false" />
+    </inspection_tool>
+    <inspection_tool class="StreamToLoop" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="StringBufferField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringBufferMustHaveInitialCapacity" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringBufferReplaceableByString" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringBufferReplaceableByStringBuilder" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringBufferToStringInConcatenation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringConcatenation" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreAsserts" value="false" />
+      <option name="ignoreSystemOuts" value="false" />
+      <option name="ignoreSystemErrs" value="false" />
+      <option name="ignoreThrowableArguments" value="false" />
+      <option name="ignoreConstantInitializers" value="false" />
+      <option name="ignoreInTestCode" value="false" />
+      <option name="ignoreInToString" value="false" />
+    </inspection_tool>
+    <inspection_tool class="StringConcatenationArgumentToLogCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringConcatenationInFormatCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringConcatenationInLoops" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringConcatenationInMessageFormatCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringConcatenationInsideStringBufferAppend" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringConcatenationMissingWhitespace" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringEquality" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringEqualsCharSequence" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringEqualsEmptyString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringLiteralBreaksHTMLJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringOperationCanBeSimplified" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringRepeatCanBeUsed" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="StringReplaceableByStringBuffer" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="onlyWarnOnLoop" value="true" />
+    </inspection_tool>
+    <inspection_tool class="StringToUpperWithoutLocale" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringTokenizer" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="StringTokenizerDelimiter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Stylelint" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="SubtractionInCompareTo" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuperTearDownInFinally" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuppressionAnnotation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuspendFunctionOnCoroutineScope" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousArrayCast" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuspiciousArrayMethodCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousAsDynamic" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousCallableReferenceInLambda" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousCollectionReassignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousDateFormat" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousEqualsCombination" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousGetterSetter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuspiciousIndentAfterControlStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousIntegerDivAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousInvocationHandlerImplementation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousListRemoveInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousLiteralUnderscore" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuspiciousLocalesLanguages" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SuspiciousMethodCalls" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="REPORT_CONVERTIBLE_METHOD_CALLS" value="true" />
+    </inspection_tool>
+    <inspection_tool class="SuspiciousNameCombination" enabled="true" level="WARNING" enabled_by_default="true">
+      <group names="x,width,left,right" />
+      <group names="y,height,top,bottom" />
+      <ignored>
+        <option name="METHOD_MATCHER_CONFIG" value="java.io.PrintStream,println,java.io.PrintWriter,println,java.lang.System,identityHashCode,java.sql.PreparedStatement,set.*,java.sql.ResultSet,update.*,java.sql.SQLOutput,write.*,java.lang.Integer,compare.*,java.lang.Long,compare.*,java.lang.Short,compare,java.lang.Byte,compare,java.lang.Character,compare,java.lang.Boolean,compare,java.lang.Math,.*,java.lang.StrictMath,.*" />
+      </ignored>
+    </inspection_tool>
+    <inspection_tool class="SuspiciousSystemArraycopy" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousTernaryOperatorInVarargsCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousToArrayCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousTypeOfGuard" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SuspiciousVarProperty" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SwJsonMaybeSpecificationInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SwYamlMaybeSpecificationInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SwitchLabeledRuleCanBeCodeBlock" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="SwitchStatement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SwitchStatementDensity" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="20" />
+    </inspection_tool>
+    <inspection_tool class="SwitchStatementWithConfusingDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SwitchStatementWithTooFewBranches" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_limit" value="2" />
+    </inspection_tool>
+    <inspection_tool class="SwitchStatementWithTooManyBranches" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="10" />
+    </inspection_tool>
+    <inspection_tool class="SwitchStatementsWithoutDefault" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="m_ignoreFullyCoveredEnums" value="true" />
+    </inspection_tool>
+    <inspection_tool class="SynchronizationOnGetClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SynchronizationOnLocalVariableOrMethodParameter" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="reportLocalVariables" value="true" />
+      <option name="reportMethodParameters" value="true" />
+    </inspection_tool>
+    <inspection_tool class="SynchronizationOnStaticField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SynchronizeOnLock" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SynchronizeOnNonFinalField" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SynchronizeOnThis" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SynchronizeOnValueBasedClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SynchronizedMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_includeNativeMethods" value="true" />
+      <option name="ignoreSynchronizedSuperMethods" value="true" />
+    </inspection_tool>
+    <inspection_tool class="SynchronizedOnLiteralObject" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SyntaxError" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="SystemExit" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SystemGC" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SystemGetenv" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SystemOutErr" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SystemProperties" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SystemRunFinalizersOnExit" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SystemSetSecurityManager" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TaglibDomModelInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="TailRecursion" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="TailRecursionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TestCaseInProductCode" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TestCaseWithConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TestCaseWithNoTestMethods" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreSupers" value="true" />
+    </inspection_tool>
+    <inspection_tool class="TestFailedLine" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TestFunctionName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TestMethodInProductCode" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TestMethodWithoutAssertion" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TestOnlyProblems" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TextBlockBackwardMigration" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="TextBlockMigration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TextLabelInSwitchStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TextLabelInSwitchStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThisEscapedInConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThisExpressionReferencesGlobalObjectJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThreadDeathRethrown" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreadDumpStack" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreadLocalNotStaticFinal" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreadPriority" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreadRun" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThreadStartInConstruction" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreadStopSuspendResume" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreadWithDefaultRunMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThreadYield" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreeNegationsPerFunctionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThreeNegationsPerMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreInEquals" value="true" />
+      <option name="ignoreInAssert" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ThrowCaughtLocally" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreRethrownExceptions" value="false" />
+    </inspection_tool>
+    <inspection_tool class="ThrowFromFinallyBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThrowFromFinallyBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThrowableNotThrown" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThrowablePrintStackTrace" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThrowablePrintedToSystemOut" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThrownExceptionsPerMethod" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_limit" value="3" />
+    </inspection_tool>
+    <inspection_tool class="ThrowsRuntimeException" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ThymeleafDialectDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ThymeleafMessagesResolveInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="ThymeleafVariablesResolveInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TimeToString" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TodoComment" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TomlUnresolvedReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TooBroadCatch" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TooBroadScope" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="m_allowConstructorAsInitializer" value="false" />
+      <option name="m_onlyLookAtBlocks" value="false" />
+    </inspection_tool>
+    <inspection_tool class="TooBroadThrows" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TrailingComma" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="TrailingSpacesInProperty" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TrailingWhitespacesInTextBlock" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TransientFieldInNonSerializableClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TransientFieldNotInitialized" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TransitionPropertiesLabel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TrivialConditionalJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TrivialFunctionalExpressionUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TrivialIf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TrivialIfJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TrivialStringConcatenation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TryFinallyCanBeTryWithResources" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TryStatementWithMultipleResources" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="TryWithIdenticalCatches" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TsLint" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TypeCustomizer" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeMayBeWeakened" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="useRighthandTypeAsWeakestTypeInAssignments" value="true" />
+      <option name="useParameterizedTypeForCollectionMethods" value="true" />
+      <option name="doNotWeakenToJavaLangObject" value="true" />
+      <option name="onlyWeakentoInterface" value="true" />
+    </inspection_tool>
+    <inspection_tool class="TypeParameterExtendsFinalClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="TypeParameterExtendsObject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeParameterFindViewById" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeParameterHidesVisibleType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptAbstractClassConstructorCanBeMadeProtected" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptCheckImport" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptConfig" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptDuplicateUnionOrIntersectionType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptExplicitMemberType" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptFieldCanBeMadeReadonly" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptLibrary" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptMissingAugmentationImport" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptMissingConfigOption" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptRedundantGenericType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptSmartCast" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptSuspiciousConstructorParameterAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptUMDGlobal" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptUnresolvedFunction" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptUnresolvedReactComponent" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptUnresolvedVariable" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptValidateGenericTypes" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptValidateJSTypes" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptValidateTypes" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UElementAsPsi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UNCHECKED_WARNING" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UNUSED_IMPORT" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UastIncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UastIncorrectMimeTypeInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnaryPlus" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UncheckedExceptionClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnclearBinaryExpression" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="UnclearPrecedenceOfBinaryExpression" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnconditionalWait" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnconstructableTestCase" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UndeclaredTests" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UndesirableClassUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnfinishedStepVerifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnhandledExceptionInJSP" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UninstantiableBinding" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UninstantiableImplementedByClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UninstantiableProvidedByClass" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnknownGuard" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnknownLanguage" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnlabeledReturnInsideLambda" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="UnnecessarilyQualifiedInnerClassAccess" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreReferencesNeedingImport" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessarilyQualifiedStaticUsage" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreStaticFieldAccesses" value="false" />
+      <option name="m_ignoreStaticMethodCalls" value="false" />
+      <option name="m_ignoreStaticAccessFromStaticContext" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessarilyQualifiedStaticallyImportedElement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryBlockStatement" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreSwitchBranches" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessaryBoxing" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryBreak" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryCallToStringValueOf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryConstantArrayCreationExpression" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryContinue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryContinueJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryDefault" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryEmptyArrayUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryExplicitNumericCast" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryFinalOnLocalVariableOrParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="m_ignoreJavadoc" value="false" />
+      <option name="ignoreInModuleStatements" value="true" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessaryInheritDoc" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryInitCause" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryJavaDocLink" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreInlineLinkToSuper" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessaryLabelJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryLabelOnBreakStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryLabelOnBreakStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryLabelOnContinueStatement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryLabelOnContinueStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryLocalVariable" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreImmediatelyReturnedVariables" value="false" />
+      <option name="m_ignoreAnnotatedVariables" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessaryLocalVariableJS" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="m_ignoreImmediatelyReturnedVariables" value="false" />
+      <option name="m_ignoreAnnotatedVariables" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessaryModifier" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryModuleDependencyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryOptInAnnotation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryParentheses" enabled="true" level="INFORMATION" enabled_by_default="true">
+      <option name="ignoreClarifyingParentheses" value="false" />
+      <option name="ignoreParenthesesOnConditionals" value="false" />
+      <option name="ignoreParenthesesOnLambdaParameter" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnnecessaryQualifiedReference" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryQualifierForThis" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryReturn" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryReturnJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessarySemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryStaticInjection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryStringEscape" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessarySuperConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessarySuperQualifier" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryTemporaryOnConversionFromString" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryTemporaryOnConversionToString" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryThis" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryToStringCall" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryUnaryMinus" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryUnboxing" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryUnicodeEscape" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryVariable" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnparsedCustomBeanInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnpredictableBigDecimalConstructorCall" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreReferences" value="true" />
+      <option name="ignoreComplexLiterals" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnqualifiedFieldAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnqualifiedInnerClassAccess" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreReferencesToLocalInnerClasses" value="true" />
+    </inspection_tool>
+    <inspection_tool class="UnqualifiedMethodAccess" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnqualifiedStaticUsage" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreStaticFieldAccesses" value="false" />
+      <option name="m_ignoreStaticMethodCalls" value="false" />
+      <option name="m_ignoreStaticAccessFromStaticContext" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnreachableCodeJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnresolvedClassReferenceRepair" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="UnresolvedMessageChannel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnresolvedPluginConfigReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnresolvedPropertyKey" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnresolvedReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnresolvedRestParam" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnsafeCastFromDynamic" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="UnsafeReturnStatementVisitor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnsafeVfsRecursion" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnsatisfiedRange" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnsecureRandomNumberGeneration" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnstableApiUsage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnstableTypeUsedInSignature" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnterminatedStatementJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreSemicolonAtEndOfBlock" value="true" />
+    </inspection_tool>
+    <inspection_tool class="UnusedAssignment" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="REPORT_PREFIX_EXPRESSIONS" value="false" />
+      <option name="REPORT_POSTFIX_EXPRESSIONS" value="true" />
+      <option name="REPORT_REDUNDANT_INITIALIZER" value="true" />
+    </inspection_tool>
+    <inspection_tool class="UnusedCatchParameterJS" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="m_ignoreCatchBlocksWithComments" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UnusedDataClassCopyResult" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedDefine" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnusedEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedLabel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedLambdaExpressionBody" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedLibrary" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnusedMainParameter" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnusedMessageFormatParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedProperty" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedReceiverParameter" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedReturnValue" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
+    <inspection_tool class="UnusedSymbol" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnusedUnaryOperator" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UpdateDependencyToLatestVersion" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="UpdateTransitionLabel" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UpperCaseFieldNameNotConstant" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseBulkOperation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseCompareMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseCouple" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseDPIAwareBorders" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseDPIAwareInsets" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseEllipsisInPropertyInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseExpressionBody" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="UseJBColor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseOfAWTPeerClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfAnotherObjectsPrivateField" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignoreSameClass" value="false" />
+      <option name="ignoreEquals" value="false" />
+    </inspection_tool>
+    <inspection_tool class="UseOfClone" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfJDBCDriverClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfObsoleteAssert" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfObsoleteDateTimeApi" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfProcessBuilder" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfPropertiesAsHashtable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UseOfSunClasses" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UsePluginIdEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UsePrimitiveTypes" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UsePropertyAccessSyntax" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseVirtualFileEquals" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseWithIndex" enabled="true" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="UselessCallOnCollection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UselessCallOnNotNull" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UtilSchemaInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UtilityClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignorableAnnotations">
+        <value />
+      </option>
+    </inspection_tool>
+    <inspection_tool class="UtilityClassCanBeEnum" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UtilityClassWithPublicConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UtilityClassWithoutPrivateConstructor" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="ignorableAnnotations">
+        <value />
+      </option>
+      <option name="ignoreClassesWithOnlyMain" value="false" />
+    </inspection_tool>
+    <inspection_tool class="VarargParameter" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="VariableNotUsedInsideIf" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="VariableTypeCanBeExplicit" enabled="true" level="INFORMATION" enabled_by_default="true" />
+    <inspection_tool class="VerboseNullabilityAndEmptiness" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="VerifyFormattedMessage" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VoidExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="VoidMethodAnnotatedWithGET" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VolatileArrayField" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="VtlDirectiveArgsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VtlFileReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VtlInterpolationsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="VtlReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VtlTypesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VulnerableCodeUsages" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="VulnerableLibrariesGlobal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="VulnerableLibrariesLocal" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="W3CssValidation" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="myCssVersion" value="css3svg" />
+      <option name="myIgnoreVendorSpecificProperties" value="false" />
+    </inspection_tool>
+    <inspection_tool class="WadlDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="WaitCalledOnCondition" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WaitNotInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WaitNotifyNotInSynchronizedContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WaitOrAwaitWithoutTimeout" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WaitWhileHoldingTwoLocks" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WaitWithoutCorrespondingNotify" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WarningOnMainUnusedParameterMigration" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="WeakerAccess" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
+      <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" />
+      <option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" />
+    </inspection_tool>
+    <inspection_tool class="WebProperties" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="WebWarnings" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WebpackConfigHighlighting" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WhenWithOnlyElse" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="WhileCanBeForeach" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WhileLoopSpinsOnField" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoreNonEmtpyLoops" value="true" />
+    </inspection_tool>
+    <inspection_tool class="WithStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WorkspaceImplAbsent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WorkspaceImplObsolete" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WrapUnaryOperator" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="WrapperTypeMayBePrimitive" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WriteOnlyObject" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="WrongPackageStatement" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="WrongPropertyKeyValueDelimiter" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="XHTMLIncompatabilitiesJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="XmlDefaultAttributeValue" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="XmlDeprecatedElement" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="XmlDuplicatedId" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XmlHighlighting" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XmlInvalidId" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XmlPathReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XmlUnboundNsPrefix" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="XmlUnusedNamespaceDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="XmlWrongFileType" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="XmlWrongRootElement" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XsltDeclarations" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XsltTemplateInvocation" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="XsltUnusedDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="XsltVariableShadowing" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="YAMLDuplicatedKeys" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="YAMLRecursiveAlias" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="YAMLSchemaDeprecation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="YAMLSchemaValidation" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="YAMLUnresolvedAlias" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="YAMLUnusedAnchor" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ZeroLengthArrayInitialization" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="dependsOnMethodTestNG" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="groupsTestNG" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="groups">
+        <value>
+          <list size="0" />
+        </value>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="unused" enabled="true" level="WEAK WARNING" enabled_by_default="true" checkParameterExcludingHierarchy="false" isSelected="true">
+      <option name="LOCAL_VARIABLE" value="true" />
+      <option name="FIELD" value="true" />
+      <option name="METHOD" value="true" />
+      <option name="CLASS" value="true" />
+      <option name="PARAMETER" value="true" />
+      <option name="REPORT_PARAMETER_FOR_PUBLIC_METHODS" value="true" />
+      <option name="ADD_MAINS_TO_ENTRIES" value="true" />
+      <option name="ADD_APPLET_TO_ENTRIES" value="true" />
+      <option name="ADD_SERVLET_TO_ENTRIES" value="true" />
+      <option name="ADD_NONJAVA_TO_ENTRIES" value="true" />
+    </inspection_tool>
+  </profile>
+</component>

+ 10 - 0
.idea/misc.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="FrameworkDetectionExcludesConfiguration">
+    <file type="web" url="file://$PROJECT_DIR$" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="azul-18" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 165 - 0
LICENSE

@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+"The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

+ 52 - 0
build.gradle

@@ -0,0 +1,52 @@
+plugins {
+    id 'java-library'
+    id 'org.openjfx.javafxplugin' version "$jfxPlugin" apply false
+    id 'org.beryx.jlink' version "$jlink" apply false
+    id 'com.vanniktech.maven.publish' version "$mavenPublishPlugin" apply false
+}
+
+group 'io.github.palexdev'
+
+subprojects {
+    apply plugin: "java-library"
+    apply plugin: "org.openjfx.javafxplugin"
+    apply plugin: "com.vanniktech.maven.publish"
+
+    repositories {
+        mavenCentral()
+    }
+
+    configurations {
+        testImplementation.extendsFrom compileOnly
+    }
+
+    dependencies {
+        testImplementation "org.junit.jupiter:junit-jupiter-api:$junit"
+        testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit"
+    }
+
+    javafx {
+        version = "$jfx"
+        modules = ["javafx.controls", "javafx.fxml"]
+        configuration = "compileOnly"
+    }
+
+    compileJava {
+        sourceCompatibility = "$jdk"
+        targetCompatibility = "$jdk"
+    }
+
+    compileTestJava {
+        // TODO this is temporary
+        sourceCompatibility = "17"
+        targetCompatibility = "17"
+    }
+
+    test {
+        useJUnitPlatform()
+
+    }
+}
+
+
+

+ 34 - 0
gradle.properties

@@ -0,0 +1,34 @@
+#--------------------------------------#
+# Maven                                #
+#--------------------------------------#
+GROUP=io.github.palexdev
+
+POM_URL=https://github.com/palexdev/MaterialFX
+POM_SCM_URL=https://github.com/palexdev/MaterialFX
+
+POM_DEVELOPER_ID=palexdev
+POM_DEVELOPER_NAME=Alessandro Parisi
+POM_DEVELOPER_URL=https://github.com/palexdev
+
+POM_PACKAGING=jar
+
+#--------------------------------------#
+# Versions                             #
+#--------------------------------------#
+jdk=11
+
+# Modules
+mfxcore=11.1.5
+mfxlocalization=11.0.1
+mfxresources=11.0.4
+
+# Plugins
+jfxPlugin=0.0.13
+jlink=2.25.0
+mavenPublishPlugin=0.22.0
+
+# Dependencies
+jfx=19
+
+# Test Dependencies
+junit=5.9.1

BIN
gradle/wrapper/gradle-wrapper.jar


+ 5 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists

+ 234 - 0
gradlew

@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"

+ 89 - 0
gradlew.bat

@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 20 - 0
modules/core/build.gradle

@@ -0,0 +1,20 @@
+import com.vanniktech.maven.publish.SonatypeHost
+
+version = "$mfxcore"
+
+dependencies {
+    api(project(":localization"))
+}
+
+java {
+    withSourcesJar()
+    withJavadocJar()
+    tasks.withType(Jar).each { it.archiveBaseName.set("mfxcore") }
+}
+
+mavenPublishing {
+    publishToMavenCentral(SonatypeHost.S01)
+    signAllPublications()
+}
+
+

+ 13 - 0
modules/core/gradle.properties

@@ -0,0 +1,13 @@
+#--------------------------------------#
+# Maven                                #
+#--------------------------------------#
+POM_ARTIFACT_ID=mfxcore
+VERSION_NAME=11.1.5
+
+POM_NAME=mfxcore
+POM_DESCRIPTION=Core components for MaterialFX
+POM_INCEPTION_YEAR=2022
+
+POM_LICENCE_NAME=GNU LGPLv3
+POM_LICENCE_URL=https://www.gnu.org/licenses/lgpl-3.0.html
+POM_LICENCE_DIST=repo

+ 176 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/animations/AnimationFactory.java

@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.animations;
+
+import javafx.animation.Interpolator;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
+import javafx.scene.Node;
+import javafx.util.Duration;
+
+/**
+ * Convenience factory for various animations applied to {@code Nodes}.
+ *
+ * @see Timeline
+ */
+public enum AnimationFactory {
+	FADE_IN {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.opacityProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.opacityProperty(), 1.0, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	FADE_OUT {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.opacityProperty(), 1.0, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.opacityProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_IN_BOTTOM {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateYProperty(), -node.getBoundsInParent().getHeight() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateYProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_OUT_BOTTOM {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateYProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateYProperty(), node.getBoundsInParent().getHeight() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_IN_LEFT {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateXProperty(), -node.getBoundsInParent().getWidth() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateXProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_OUT_LEFT {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateXProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateXProperty(), -node.getBoundsInParent().getWidth() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_IN_RIGHT {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateXProperty(), node.getBoundsInParent().getWidth() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateXProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_OUT_RIGHT {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateXProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateXProperty(), node.getBoundsInParent().getWidth() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_IN_TOP {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateYProperty(), node.getBoundsInParent().getHeight() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateYProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	},
+	SLIDE_OUT_TOP {
+		@Override
+		public Timeline build(Node node, double durationMillis) {
+			AnimationFactory.resetNode(node);
+			KeyValue keyValue1 = new KeyValue(node.translateYProperty(), 0, INTERPOLATOR_V1);
+			KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
+
+			KeyValue keyValue2 = new KeyValue(node.translateYProperty(), -node.getBoundsInParent().getHeight() * 2, INTERPOLATOR_V1);
+			KeyFrame keyFrame2 = new KeyFrame(Duration.millis(durationMillis), keyValue2);
+
+			return new Timeline(keyFrame1, keyFrame2);
+		}
+	};
+
+	public static final Interpolator INTERPOLATOR_V1 = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
+	public static final Interpolator INTERPOLATOR_V2 = Interpolator.SPLINE(0.0825D, 0.3025D, 0.0875D, 0.9975D);
+
+	private static void resetNode(Node node) {
+		if (node != null) {
+			node.setTranslateX(0);
+			node.setTranslateY(0);
+		}
+	}
+
+	public abstract Timeline build(Node node, double durationMillis);
+}

+ 892 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/animations/Animations.java

@@ -0,0 +1,892 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.animations;
+
+import io.github.palexdev.mfxcore.base.beans.AnimationsData;
+import javafx.animation.*;
+import javafx.beans.binding.BooleanExpression;
+import javafx.beans.value.WritableValue;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.Node;
+import javafx.scene.control.Labeled;
+import javafx.scene.text.Text;
+import javafx.stage.Window;
+import javafx.util.Duration;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+/**
+ * Utility class to easily build animations of any sort. Designed with fluent api.
+ */
+public class Animations {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	private Animations() {
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * Temporarily disables the given node for the specified duration.
+	 */
+	public static void disableTemporarily(Duration duration, Node node) {
+		node.setDisable(true);
+		Animations.PauseBuilder.build()
+				.setOnFinished(event -> node.setDisable(false))
+				.setDuration(duration)
+				.getAnimation()
+				.play();
+	}
+
+	/**
+	 * Calls {@link #disableTemporarily(Duration, Node)} by converting the given millis value
+	 * with {@link Duration#millis(double)}.
+	 */
+	public static void disableTemporarily(double millis, Node node) {
+		disableTemporarily(Duration.millis(millis), node);
+	}
+
+	/**
+	 * Executes the given onFinished action after the specified duration of time.
+	 * (Uses a PauseTransition)
+	 */
+	public static void executeLater(Duration duration, EventHandler<ActionEvent> onFinished) {
+		PauseBuilder.build().setDuration(duration).setOnFinished(onFinished).getAnimation().play();
+	}
+
+	/**
+	 * Calls {@link #executeLater(Duration, EventHandler)} by converting the given millis value
+	 * with {@link Duration#millis(double)}.
+	 */
+	public static void executeLater(double millis, EventHandler<ActionEvent> onFinished) {
+		executeLater(Duration.millis(millis), onFinished);
+	}
+
+	/**
+	 * Sets the text of the given {@link Labeled} with a fade out/fade in transition.
+	 *
+	 * @param labeled  the labeled control to change the text to
+	 * @param duration the fade in and fade out speed
+	 * @param nexText  the new text to set
+	 * @return an instance of {@link AbstractBuilder}
+	 */
+	public static AbstractBuilder transitionText(Labeled labeled, Duration duration, String nexText) {
+		return SequentialBuilder.build()
+				.hide(AnimationsData.of(labeled, duration, event -> labeled.setText(nexText)))
+				.show(AnimationsData.of(labeled, duration));
+	}
+
+	/**
+	 * Calls {@link #transitionText(Labeled, Duration, String)} by converting the given millis value
+	 * with {@link Duration#millis(double)}.
+	 */
+	public static AbstractBuilder transitionText(Labeled labeled, double millis, String nexText) {
+		return transitionText(labeled, Duration.millis(millis), nexText);
+	}
+
+	/**
+	 * Sets the text of the given {@link Text} with a fade out/fade in transition.
+	 *
+	 * @param text     the text control to change the text to
+	 * @param duration the fade in and fade out speed
+	 * @param nexText  the new text to set
+	 * @return an instance of {@link AbstractBuilder}
+	 */
+	public static AbstractBuilder transitionText(Text text, Duration duration, String nexText) {
+		return SequentialBuilder.build()
+				.hide(AnimationsData.of(text, duration, event -> text.setText(nexText)))
+				.show(AnimationsData.of(text, duration));
+	}
+
+	/**
+	 * Calls {@link #transitionText(Text, Duration, String)} by converting the given millis value
+	 * with {@link Duration#millis(double)}.
+	 */
+	public static AbstractBuilder transitionText(Text text, double millis, String nexText) {
+		return transitionText(text, Duration.millis(millis), nexText);
+	}
+
+	/**
+	 * @return true if the given animation status is RUNNING, otherwise false
+	 */
+	public static boolean isPlaying(Animation animation) {
+		return animation.getStatus() == Animation.Status.RUNNING;
+	}
+
+	/**
+	 * @return true if the given animation status is PAUSED, otherwise false
+	 */
+	public static boolean isPaused(Animation animation) {
+		return animation.getStatus() == Animation.Status.PAUSED;
+	}
+
+	public static boolean isStopped(Animation animation) {
+		return animation.getStatus() == Animation.Status.STOPPED;
+	}
+
+	//================================================================================
+	// Builders
+	//================================================================================
+
+	/**
+	 * Common base class for {@link ParallelBuilder} and {@link SequentialBuilder}.
+	 * <p></p>
+	 * This builder, designed with fluent api, allows you to create simple and complex animations with just a few lines of code.
+	 * <p></p>
+	 * The builder keeps the reference of the "main" animation (depending on the subclass can be ParallelTransition or SequentialTransition, in
+	 * the AbstractBuilder the type is a generic {@link Animation}), and defines and abstract method that subclasses must implement
+	 * to properly add animations to the "main".
+	 */
+	public static abstract class AbstractBuilder {
+		//================================================================================
+		// Properties
+		//================================================================================
+		protected Animation animation;
+
+		//================================================================================
+		// Abstract Methods
+		//================================================================================
+
+		/**
+		 * Adds the given animation to the "main" animation.
+		 */
+		protected abstract void addAnimation(Animation animation);
+
+		/**
+		 * @return the "main" animation instance
+		 */
+		public abstract Animation getAnimation();
+
+		//================================================================================
+		// Methods
+		//================================================================================
+		protected void init(Animation animation) {
+			this.animation = animation;
+		}
+
+		/**
+		 * Adds the given animation to the "main" animation by calling {@link #addAnimation(Animation)}.
+		 */
+		public AbstractBuilder add(Animation animation) {
+			addAnimation(animation);
+			return this;
+		}
+
+		/**
+		 * Sets the given onFinished action to the given animation and then adds it to the
+		 * "main" animation by calling {@link #addAnimation(Animation)}.
+		 */
+		public AbstractBuilder add(Animation animation, EventHandler<ActionEvent> onFinished) {
+			animation.setOnFinished(onFinished);
+			addAnimation(animation);
+			return this;
+		}
+
+		/**
+		 * Gets the animation from the supplier and adds it to the "main" animation by calling {@link #addAnimation(Animation)}.
+		 */
+		public AbstractBuilder add(Supplier<Animation> animationSupplier) {
+			addAnimation(animationSupplier.get());
+			return this;
+		}
+
+		/**
+		 * Gets the animation from the supplier, sets the given onFinished action to it and then adds it to the
+		 * "main" animation by calling {@link #addAnimation(Animation)}.
+		 */
+		public AbstractBuilder add(Supplier<Animation> animationSupplier, EventHandler<ActionEvent> onFinished) {
+			Animation animation = animationSupplier.get();
+			animation.setOnFinished(onFinished);
+			addAnimation(animation);
+			return this;
+		}
+
+		/**
+		 * Builds a {@link Timeline} with the given keyframes and adds it to the "main" animation by calling {@link #addAnimation(Animation)}.
+		 */
+		public AbstractBuilder add(KeyFrame... keyFrames) {
+			addAnimation(new Timeline(keyFrames));
+			return this;
+		}
+
+		/**
+		 * Builds a {@link Timeline} with the given keyframes, sets the given onFinished action to it and then adds it to the
+		 * "main" animation by calling {@link #addAnimation(Animation)}.
+		 */
+		public AbstractBuilder add(EventHandler<ActionEvent> onFinished, KeyFrame... keyFrames) {
+			addAnimation(TimelineBuilder.build().add(keyFrames).setOnFinished(onFinished).getAnimation());
+			return this;
+		}
+
+
+		/**
+		 * For each given node builds and adds an animation that disables the node
+		 * after the given duration of time.
+		 *
+		 * @param duration the time after which the nodes are disabled
+		 */
+		public AbstractBuilder disable(Duration duration, Node... nodes) {
+			for (Node node : nodes) {
+				addAnimation(
+						PauseBuilder.build()
+								.setDuration(duration)
+								.setOnFinished(end -> node.setDisable(true))
+								.getAnimation()
+				);
+			}
+			return this;
+		}
+
+		/**
+		 * For each given node builds and adds an animation that enables the node
+		 * after the given duration of time.
+		 *
+		 * @param duration the duration after which the nodes are enabled
+		 */
+		public AbstractBuilder enable(Duration duration, Node... nodes) {
+			for (Node node : nodes) {
+				addAnimation(
+						PauseBuilder.build()
+								.setDuration(duration)
+								.setOnFinished(end -> node.setDisable(false))
+								.getAnimation()
+				);
+			}
+			return this;
+		}
+
+		/**
+		 * For each given window builds and adds an animation that hides the window by fading it out.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public AbstractBuilder hide(Duration duration, Window... windows) {
+			for (Window window : windows) {
+				addAnimation(TimelineBuilder.build().add(KeyFrames.of(duration, window.opacityProperty(), 0)).getAnimation());
+			}
+			return this;
+		}
+
+		/**
+		 * Calls {@link #hide(Duration, Window...)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public AbstractBuilder hide(double millis, Window... windows) {
+			return hide(Duration.millis(millis), windows);
+		}
+
+		/**
+		 * For each given node builds and adds an animation that hides the node by fading it out.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public AbstractBuilder hide(Duration duration, Node... nodes) {
+			for (Node node : nodes) {
+				addAnimation(TimelineBuilder.build().hide(duration, node).getAnimation());
+			}
+			return this;
+		}
+
+		/**
+		 * Calls {@link #hide(Duration, Node...)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public AbstractBuilder hide(double millis, Node... nodes) {
+			return hide(Duration.millis(millis), nodes);
+		}
+
+		/**
+		 * Creates and adds a fade out animation for each given {@link AnimationsData}.
+		 */
+		public final AbstractBuilder hide(AnimationsData... data) {
+			for (AnimationsData animData : data) {
+				addAnimation(TimelineBuilder.build().hide(animData).getAnimation());
+			}
+			return this;
+		}
+
+		/**
+		 * For each given window builds and adds an animation that shows the window by fading it in.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public AbstractBuilder show(Duration duration, Window... windows) {
+			for (Window window : windows) {
+				addAnimation(TimelineBuilder.build().show(duration, window).getAnimation());
+			}
+			return this;
+		}
+
+		/**
+		 * Calls {@link #show(Duration, Window...)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public AbstractBuilder show(double millis, Window... windows) {
+			return show(Duration.millis(millis), windows);
+		}
+
+		/**
+		 * For each given node builds and adds an animation that shows the node by fading it in.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public AbstractBuilder show(Duration duration, Node... nodes) {
+			for (Node node : nodes) {
+				addAnimation(TimelineBuilder.build().show(duration, node).getAnimation());
+			}
+			return this;
+		}
+
+		/**
+		 * Calls {@link #show(Duration, Node...)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public AbstractBuilder show(double millis, Node... nodes) {
+			return show(Duration.millis(millis), nodes);
+		}
+
+		/**
+		 * Creates and adds a fade in animation for each given {@link AnimationsData}.
+		 */
+		public final AbstractBuilder show(AnimationsData... data) {
+			for (AnimationsData animData : data) {
+				addAnimation(TimelineBuilder.build().show(animData).getAnimation());
+			}
+			return this;
+		}
+
+		/**
+		 * Sets the action to perform when the "main" animation ends.
+		 */
+		public AbstractBuilder setOnFinished(EventHandler<ActionEvent> onFinished) {
+			animation.setOnFinished(onFinished);
+			return this;
+		}
+
+		/**
+		 * Sets the "main" animation cycle count.
+		 */
+		public AbstractBuilder setCycleCount(int cycleCount) {
+			animation.setCycleCount(cycleCount);
+			return this;
+		}
+
+		/**
+		 * Sets the "main" animation delay.
+		 */
+		public AbstractBuilder setDelay(Duration delay) {
+			animation.setDelay(delay);
+			return this;
+		}
+
+		/**
+		 * Sets the "main" animation delay.
+		 */
+		public AbstractBuilder setDelay(double millis) {
+			animation.setDelay(Duration.millis(millis));
+			return this;
+		}
+
+		/**
+		 * Sets the "main" animation rate/speed.
+		 */
+		public AbstractBuilder setRate(double rate) {
+			animation.setRate(rate);
+			return this;
+		}
+	}
+
+	/**
+	 * Implementation of {@link AbstractBuilder} that uses a {@link SequentialTransition} as "main" animation.
+	 */
+	public static class SequentialBuilder extends AbstractBuilder {
+		//================================================================================
+		// Properties
+		//================================================================================
+		private final SequentialTransition sequentialTransition = new SequentialTransition();
+
+		//================================================================================
+		// Constructors
+		//================================================================================
+		public SequentialBuilder() {
+			init(sequentialTransition);
+		}
+
+		//================================================================================
+		// Static Methods
+		//================================================================================
+
+		/**
+		 * @return a new SequentialBuilder instance. Equivalent to calling the constructor,
+		 * it's just a way to omit the new keyword
+		 */
+		public static SequentialBuilder build() {
+			return new SequentialBuilder();
+		}
+
+		//================================================================================
+		// Override Methods
+		//================================================================================
+		@Override
+		protected void addAnimation(Animation animation) {
+			sequentialTransition.getChildren().add(animation);
+		}
+
+		@Override
+		public SequentialTransition getAnimation() {
+			return sequentialTransition;
+		}
+	}
+
+	/**
+	 * Implementation of {@link AbstractBuilder} that uses a {@link ParallelTransition} as "main" animation.
+	 */
+	public static class ParallelBuilder extends AbstractBuilder {
+		//================================================================================
+		// Properties
+		//================================================================================
+		private final ParallelTransition parallelTransition = new ParallelTransition();
+
+		//================================================================================
+		// Constructors
+		//================================================================================
+		public ParallelBuilder() {
+			init(parallelTransition);
+		}
+
+		//================================================================================
+		// Static Methods
+		//================================================================================
+
+		/**
+		 * @return a new ParallelBuilder instance. Equivalent to calling the constructor,
+		 * it's just a way to omit the new keyword
+		 */
+		public static ParallelBuilder build() {
+			return new ParallelBuilder();
+		}
+
+		//================================================================================
+		// Override Methods
+		//================================================================================
+		@Override
+		protected void addAnimation(Animation animation) {
+			parallelTransition.getChildren().add(animation);
+		}
+
+		@Override
+		public ParallelTransition getAnimation() {
+			return parallelTransition;
+		}
+	}
+
+	/**
+	 * Builder class to easily create a {@link Timeline} with fluent api.
+	 */
+	public static class TimelineBuilder {
+		//================================================================================
+		// Properties
+		//================================================================================
+		private final Timeline timeline = new Timeline();
+
+		/**
+		 * @return a new TimelineBuilder instance. Equivalent to calling the constructor,
+		 * it's just a way to omit the new keyword
+		 */
+		public static TimelineBuilder build() {
+			return new TimelineBuilder();
+		}
+
+		//================================================================================
+		// Methods
+		//================================================================================
+
+		/**
+		 * Adds the specified KeyFrames to the timeline.
+		 */
+		public TimelineBuilder add(KeyFrame... keyFrames) {
+			timeline.getKeyFrames().addAll(Arrays.asList(keyFrames));
+			return this;
+		}
+
+		/**
+		 * Builds a KeyFrame to hide the given Window by fading it out.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public TimelineBuilder hide(Duration duration, Window window) {
+			add(KeyFrames.of(duration, window.opacityProperty(), 0));
+			return this;
+		}
+
+		/**
+		 * Calls {@link #hide(Duration, Window)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public TimelineBuilder hide(double millis, Window window) {
+			return hide(Duration.millis(millis), window);
+		}
+
+		/**
+		 * Builds the KeyFrames to hide the given node by fading it out.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public TimelineBuilder hide(Duration duration, Node node) {
+			add(
+					KeyFrames.of(Duration.ZERO, node.opacityProperty(), 1.0, AnimationFactory.INTERPOLATOR_V1),
+					KeyFrames.of(duration, node.opacityProperty(), 0, AnimationFactory.INTERPOLATOR_V1)
+			);
+			return this;
+		}
+
+		/**
+		 * Calls {@link #hide(Duration, Node)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public TimelineBuilder hide(double millis, Node node) {
+			return hide(Duration.millis(millis), node);
+		}
+
+		/**
+		 * Builds the KeyFrames to hide the specified node in the AnimationsData bean, by fading it out.
+		 */
+		public final TimelineBuilder hide(AnimationsData data) {
+			add(
+					KeyFrames.of(Duration.ZERO, data.getNode().opacityProperty(), 1.0),
+					KeyFrames.of(data.getDuration(), data.getNode().opacityProperty(), 0.0)
+			);
+			setOnFinished(data.getOnFinished());
+			return this;
+		}
+
+		/**
+		 * Builds a KeyFrame to show the given Window by fading it in.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public TimelineBuilder show(Duration duration, Window window) {
+			add(KeyFrames.of(duration, window.opacityProperty(), 1.0));
+			return this;
+		}
+
+		/**
+		 * Calls {@link #show(Duration, Window)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public TimelineBuilder show(double millis, Window window) {
+			return show(Duration.millis(millis), window);
+		}
+
+		/**
+		 * Builds the KeyFrames to show the given node by fading it in.
+		 *
+		 * @param duration the fade animation speed
+		 */
+		public TimelineBuilder show(Duration duration, Node node) {
+			add(
+					KeyFrames.of(Duration.ZERO, node.opacityProperty(), 0.0),
+					KeyFrames.of(duration, node.opacityProperty(), 1.0)
+			);
+			return this;
+		}
+
+		/**
+		 * Calls {@link #show(Duration, Node)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public TimelineBuilder show(double millis, Node node) {
+			return show(Duration.millis(millis), node);
+		}
+
+		/**
+		 * Creates and adds a fade in animation for each given {@link AnimationsData}.
+		 */
+		public final TimelineBuilder show(AnimationsData data) {
+			add(
+					KeyFrames.of(Duration.ZERO, data.getNode().opacityProperty(), 0.0),
+					KeyFrames.of(data.getDuration(), data.getNode().opacityProperty(), 1.0)
+			);
+			setOnFinished(data.getOnFinished());
+			return this;
+		}
+
+		/**
+		 * Sets the timeline cycle count.
+		 */
+		public TimelineBuilder setCycleCount(int cycleCount) {
+			timeline.setCycleCount(cycleCount);
+			return this;
+		}
+
+		/**
+		 * Sets the timeline delay.
+		 */
+		public TimelineBuilder setDelay(Duration delay) {
+			timeline.setDelay(delay);
+			return this;
+		}
+
+		/**
+		 * Sets the timeline delay.
+		 */
+		public TimelineBuilder setDelay(double millis) {
+			timeline.setDelay(Duration.millis(millis));
+			return this;
+		}
+
+		/**
+		 * Sets the timeline rate/speed.
+		 */
+		public TimelineBuilder setRate(double rate) {
+			timeline.setRate(rate);
+			return this;
+		}
+
+		/**
+		 * Sets the action to perform when the timeline ends.
+		 */
+		public TimelineBuilder setOnFinished(EventHandler<ActionEvent> onFinished) {
+			timeline.setOnFinished(onFinished);
+			return this;
+		}
+
+		/**
+		 * @return the instance of the Timeline
+		 */
+		public Timeline getAnimation() {
+			return timeline;
+		}
+	}
+
+	/**
+	 * Builder class to easily create a {@link PauseTransition} with fluent api.
+	 */
+	public static class PauseBuilder {
+		//================================================================================
+		// Properties
+		//================================================================================
+		private final PauseTransition pauseTransition = new PauseTransition();
+
+		//================================================================================
+		// Static Methods
+		//================================================================================
+
+		/**
+		 * @return a new PauseBuilder instance. Equivalent to calling the constructor,
+		 * it's just a way to omit the new keyword
+		 */
+		public static PauseBuilder build() {
+			return new PauseBuilder();
+		}
+
+		//================================================================================
+		// Methods
+		//================================================================================
+
+		public Animations.PauseBuilder setDelay(Duration duration) {
+			pauseTransition.setDelay(duration);
+			return this;
+		}
+
+		public Animations.PauseBuilder setDelay(double millis) {
+			pauseTransition.setDelay(Duration.millis(millis));
+			return this;
+		}
+
+		/**
+		 * Sets the pause transition duration.
+		 */
+		public PauseBuilder setDuration(Duration duration) {
+			pauseTransition.setDuration(duration);
+			return this;
+		}
+
+		/**
+		 * Calls {@link #setDuration(Duration)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public PauseBuilder setDuration(double millis) {
+			pauseTransition.setDuration(Duration.millis(millis));
+			return this;
+		}
+
+		/**
+		 * Sets the action to perform when the pause transition ends.
+		 */
+		public PauseBuilder setOnFinished(EventHandler<ActionEvent> onFinished) {
+			pauseTransition.setOnFinished(onFinished);
+			return this;
+		}
+
+		/**
+		 * @return the instance of the PauseTransition
+		 */
+		public PauseTransition getAnimation() {
+			return pauseTransition;
+		}
+
+		/**
+		 * This method can be considered an utility.
+		 * <p></p>
+		 * A {@link PauseTransition} with the previously set duration runs while the given boolean boolean expression
+		 * is false. When the expression is evaluated and it is false the given retryAction is run and the transition
+		 * is restarted. When it ends the expression is re-evaluated. When the expression becomes true the onSuccessAction is run.
+		 * <p></p>
+		 * So you have a {@link PauseTransition} that runs every tot unit of time and stops only when the given expression is true.
+		 *
+		 * @param booleanExpression the expression to check at a fixed time rate
+		 * @param retryAction       the action to perform when the expression is false
+		 * @param onSuccessAction   the action to perform when the expression is true
+		 */
+		public void runWhile(BooleanExpression booleanExpression, Runnable retryAction, Runnable onSuccessAction) {
+			setOnFinished(event -> {
+				if (!booleanExpression.get()) {
+					retryAction.run();
+					getAnimation().playFromStart();
+				} else {
+					onSuccessAction.run();
+				}
+			});
+			getAnimation().play();
+		}
+
+		/**
+		 * Same method as {@link #runWhile(BooleanExpression, Runnable, Runnable)} but instead of running
+		 * until the given expression is true, it is limited to a maximum number of retries.
+		 *
+		 * @param maxRetryCount the max number of times the transition can be restarted
+		 */
+		public void runWhile(BooleanExpression booleanExpression, Runnable retryAction, Runnable onSuccessAction, int maxRetryCount) {
+			AtomicInteger retryCount = new AtomicInteger(0);
+			setOnFinished(event -> {
+				if (!booleanExpression.get() && retryCount.get() < maxRetryCount) {
+					retryCount.getAndIncrement();
+					retryAction.run();
+					getAnimation().playFromStart();
+				} else {
+					onSuccessAction.run();
+				}
+			});
+			getAnimation().play();
+		}
+	}
+
+	/**
+	 * Builder class for keyframes and keyvalues.
+	 */
+	public static class KeyFrames {
+
+		//================================================================================
+		// Constructors
+		//================================================================================
+		private KeyFrames() {
+		}
+
+		//================================================================================
+		// Static Methods
+		//================================================================================
+
+		/**
+		 * Returns a new KeyFrame with the given duration and action.
+		 */
+		public static KeyFrame of(Duration duration, EventHandler<ActionEvent> action) {
+			return new KeyFrame(duration, action);
+		}
+
+		/**
+		 * Calls {@link #of(Duration, EventHandler)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public static KeyFrame of(double millis, EventHandler<ActionEvent> action) {
+			return of(Duration.millis(millis), action);
+		}
+
+		/**
+		 * Returns a new KeyFrame with the given duration and keyvalues.
+		 */
+		public static KeyFrame of(Duration duration, KeyValue... keyValues) {
+			return new KeyFrame(duration, keyValues);
+		}
+
+		/**
+		 * Calls {@link #of(Duration, KeyValue[])} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public static KeyFrame of(double millis, KeyValue... keyValues) {
+			return of(Duration.millis(millis), keyValues);
+		}
+
+		/**
+		 * Returns a new KeyFrame with the given duration and builds a new KeyValue for it
+		 * with the given writable property and endValue.
+		 */
+		public static <T> KeyFrame of(Duration duration, WritableValue<T> writableValue, T endValue) {
+			return of(duration, new KeyValue(writableValue, endValue));
+		}
+
+		/**
+		 * Calls {@link #of(Duration, WritableValue, Object)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public static <T> KeyFrame of(double millis, WritableValue<T> writableValue, T endValue) {
+			return of(Duration.millis(millis), writableValue, endValue);
+		}
+
+		/**
+		 * Returns a new KeyFrame with the given duration and builds a new KeyValue for it
+		 * with the given writable property, endValue and interpolator.
+		 */
+		public static <T> KeyFrame of(Duration duration, WritableValue<T> writableValue, T endValue, Interpolator interpolator) {
+			return of(duration, new KeyValue(writableValue, endValue, interpolator));
+		}
+
+		/**
+		 * Calls {@link #of(Duration, WritableValue, Object, Interpolator)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public static <T> KeyFrame of(double millis, WritableValue<T> writableValue, T endValue, Interpolator interpolator) {
+			return of(Duration.millis(millis), writableValue, endValue, interpolator);
+		}
+
+		/**
+		 * Returns a new KeyFrame with the given duration and builds a new KeyValue for it
+		 * with the given writable property, endValue and interpolator.
+		 */
+		public static <T> KeyFrame of(Duration duration, WritableValue<T> writableValue, T endValue, Interpolators interpolator) {
+			return of(duration, new KeyValue(writableValue, endValue, interpolator.toInterpolator()));
+		}
+
+		/**
+		 * Calls {@link #of(Duration, WritableValue, Object, Interpolators)} by converting the given millis value
+		 * with {@link Duration#millis(double)}.
+		 */
+		public static <T> KeyFrame of(double millis, WritableValue<T> writableValue, T endValue, Interpolators interpolator) {
+			return of(Duration.millis(millis), writableValue, endValue, interpolator.toInterpolator());
+		}
+	}
+}
+

+ 133 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/animations/BezierEasing.java

@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.animations;
+
+import javafx.animation.Interpolator;
+
+/**
+ * Cubic Bezier implementation from <a href="https://github.com/gre/bezier-easing">https://github.com/gre/bezier-easing</a>
+ * <p>
+ * Make sure to check this tool out! <a href="https://cubic-bezier.com/#0,0,.58,1">https://cubic-bezier.com</a>
+ */
+public class BezierEasing {
+	private static final int NEWTON_ITERATIONS = 4;
+	private static final double NEWTON_MIN_SLOPE = 0.001;
+	private static final double SUBDIVISION_PRECISION = 0.0000001;
+	private static final int SUBDIVISION_MAX_ITERATIONS = 10;
+
+	private static final int kSplineTableSize = 11;
+	private static final double kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
+
+	public static final Interpolator EASE = toInterpolator(.25, 1, .25, 1);
+	public static final Interpolator LINEAR = toInterpolator(0, 0, 1, 1);
+	public static final Interpolator EASE_IN = toInterpolator(.42, 0, 1, 1);
+	public static final Interpolator EASE_OUT = toInterpolator(0, 0, .58, 1);
+	public static final Interpolator EASE_BOTH = toInterpolator(.42, 0, .58, 1);
+
+	private BezierEasing() {
+	}
+
+	private static double a(double a1, double a2) {
+		return 1.0 - 3.0 * a2 + 3.0 * a1;
+	}
+
+	private static double b(double a1, double a2) {
+		return 3.0 * a2 - 6.0 * a1;
+	}
+
+	private static double c(double a1) {
+		return 3.0 * a1;
+	}
+
+	private static double calcBezier(double t, double a1, double a2) {
+		return ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t;
+	}
+
+	// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
+	private static double getSlope(double aT, double aA1, double aA2) {
+		return 3.0 * a(aA1, aA2) * aT * aT + 2.0 * b(aA1, aA2) * aT + c(aA1);
+	}
+
+	private static double binarySubdivide(double aX, double aA, double aB, double mX1, double mX2) {
+		double currentX, currentT, i = 0;
+		do {
+			currentT = aA + (aB - aA) / 2.0;
+			currentX = calcBezier(currentT, mX1, mX2) - aX;
+			if (currentX > 0.0) {
+				aB = currentT;
+			} else {
+				aA = currentT;
+			}
+		} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
+		return currentT;
+	}
+
+	private static double newtonRaphsonIterate(double aX, double aGuessT, double mX1, double mX2) {
+		for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
+			var currentSlope = getSlope(aGuessT, mX1, mX2);
+			if (currentSlope == 0.0) {
+				return aGuessT;
+			}
+			var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
+			aGuessT -= currentX / currentSlope;
+		}
+		return aGuessT;
+	}
+
+	public static double bezier(double frac, double x1, double y1, double x2, double y2) {
+		double[] values = new double[kSplineTableSize];
+		for (int i = 0; i < values.length; ++i) {
+			values[i] = calcBezier(i * kSampleStepSize, x1, x2);
+		}
+
+		double intervalStart = 0.0;
+		int currentSample = 1;
+		double lastSample = kSplineTableSize - 1;
+
+		for (; currentSample != lastSample && values[currentSample] <= frac; ++currentSample) {
+			intervalStart += kSampleStepSize;
+		}
+		--currentSample;
+
+		// Interpolate to provide an initial guess for t
+		double dist = (frac - values[currentSample]) / (values[currentSample + 1] - values[currentSample]);
+		double guessForT = intervalStart + dist * kSampleStepSize;
+
+		double initialSlope = getSlope(guessForT, x1, x2);
+		double fracToT;
+		if (initialSlope >= NEWTON_MIN_SLOPE) {
+			fracToT = newtonRaphsonIterate(frac, guessForT, x1, x2);
+		} else if (initialSlope == 0.0) {
+			fracToT = guessForT;
+		} else {
+			fracToT = binarySubdivide(frac, intervalStart, intervalStart + kSampleStepSize, x1, x2);
+		}
+
+		return calcBezier(fracToT, y1, y2);
+	}
+
+	public static Interpolator toInterpolator(double x1, double y1, double x2, double y2) {
+		return new Interpolator() {
+			@Override
+			protected double curve(double t) {
+				return bezier(t, x1, y1, x2, y2);
+			}
+		};
+	}
+}

+ 167 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/animations/ConsumerTransition.java

@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.animations;
+
+import javafx.animation.Interpolator;
+import javafx.animation.Transition;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.util.Duration;
+
+import java.util.function.Consumer;
+
+/**
+ * A simple implementation of {@link Transition} that allows to specify
+ * what to do when the {@link #interpolate(double)} method is called by using
+ * a {@link Consumer}.
+ */
+public class ConsumerTransition extends Transition {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private Consumer<Double> interpolateConsumer;
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Sets the transition duration.
+	 */
+	public ConsumerTransition setDuration(Duration duration) {
+		this.setCycleDuration(duration);
+		return this;
+	}
+
+	/**
+	 * Sets the transition duration in milliseconds.
+	 */
+	public ConsumerTransition setDuration(double millis) {
+		this.setCycleDuration(Duration.millis(millis));
+		return this;
+	}
+
+	/**
+	 * Sets the consumer used by the {@link #interpolate(double)} method.
+	 */
+	public ConsumerTransition setInterpolateConsumer(Consumer<Double> interpolateConsumer) {
+		this.interpolateConsumer = interpolateConsumer;
+		return this;
+	}
+
+	/**
+	 * Sets the transition's interpolator.
+	 */
+	public ConsumerTransition setInterpolatorFluent(Interpolator interpolator) {
+		this.setInterpolator(interpolator);
+		return this;
+	}
+
+	public ConsumerTransition setInterpolatorFluent(Interpolators interpolator) {
+		return setInterpolatorFluent(interpolator.toInterpolator());
+	}
+
+	/**
+	 * Sets the transition's delay.
+	 */
+	public ConsumerTransition setDelayFluent(Duration duration) {
+		this.setDelay(duration);
+		return this;
+	}
+
+	public ConsumerTransition setOnFinishedFluent(EventHandler<ActionEvent> handler) {
+		setOnFinished(handler);
+		return this;
+	}
+
+	/**
+	 * Calls {@link #setInterpolateConsumer(Consumer)} and then starts the animation.
+	 */
+	public void playWithConsumer(Consumer<Double> interpolateConsumer) {
+		setInterpolateConsumer(interpolateConsumer);
+		this.play();
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Implementation to make use of a {@link Consumer}.
+	 */
+	@Override
+	protected void interpolate(double frac) {
+		this.interpolateConsumer.accept(frac);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer);
+	}
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer and duration.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer, Duration duration) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer).setDuration(duration);
+	}
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer and duration in milliseconds.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer, double duration) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer).setDuration(duration);
+	}
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer, duration and interpolator.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer, Duration duration, Interpolator interpolator) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer).setDuration(duration).setInterpolatorFluent(interpolator);
+	}
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer, duration in milliseconds and interpolator.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer, double duration, Interpolator interpolator) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer).setDuration(duration).setInterpolatorFluent(interpolator);
+	}
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer, duration and interpolator.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer, Duration duration, Interpolators interpolator) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer).setDuration(duration).setInterpolatorFluent(interpolator.toInterpolator());
+	}
+
+	/**
+	 * Creates a new {@code ConsumerTransition} with the given consumer, duration in milliseconds and interpolator.
+	 */
+	public static ConsumerTransition of(Consumer<Double> interpolateConsumer, double duration, Interpolators interpolator) {
+		return (new ConsumerTransition()).setInterpolateConsumer(interpolateConsumer).setDuration(duration).setInterpolatorFluent(interpolator.toInterpolator());
+	}
+}

+ 117 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/animations/Interpolators.java

@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.animations;
+
+import javafx.animation.Interpolator;
+
+import java.util.function.Function;
+
+/**
+ * Enumerator that offers some new {@link Interpolator}s for JavaFX's animations.
+ */
+public enum Interpolators {
+	INTERPOLATOR_V1(null) {
+		public Interpolator toInterpolator() {
+			return Interpolator.SPLINE(0.25D, 0.1D, 0.25D, 1.0D);
+		}
+	},
+	INTERPOLATOR_V2(null) {
+		public Interpolator toInterpolator() {
+			return Interpolator.SPLINE(0.0825D, 0.3025D, 0.0875D, 0.9975D);
+		}
+	},
+	LINEAR((t) -> t) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	},
+	EASE_IN((t) -> t * t * t) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	},
+	EASE_IN_SINE((t) -> 1.0D - Math.cos(t * 3.141592653589793D / 2.0D)) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	},
+	EASE_OUT((t) -> 1.0D - (1.0D - t) * (1.0D - t) * (1.0D - t)) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	},
+	EASE_OUT_SINE((t) -> Math.sin(t * 3.141592653589793D / 2.0D)) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	},
+	EASE_IN_OUT((t) -> t < 0.5D ? 4.0D * t * t * t : 1.0D - Math.pow(-2.0D * t + 2.0D, 3.0D) / 2.0D) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	},
+	EASE_IN_OUT_SINE((t) -> -(Math.cos(3.141592653589793D * t) - 1.0D) / 2.0D) {
+		public Interpolator toInterpolator() {
+			return new Interpolator() {
+				protected double curve(double t) {
+					return getCurve().apply(t);
+				}
+			};
+		}
+	};
+
+	private final Function<Double, Double> curve;
+
+	Interpolators(Function<Double, Double> curve) {
+		this.curve = curve;
+	}
+
+	/**
+	 * Converts a {@code Function<Double, Double>} to a JavaFX's {@link Interpolator}.
+	 */
+	public abstract Interpolator toInterpolator();
+
+	public Function<Double, Double> getCurve() {
+		return this.curve;
+	}
+}

+ 282 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/animations/MomentumTransition.java

@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.animations;
+
+import javafx.animation.Interpolator;
+import javafx.animation.Transition;
+import javafx.util.Duration;
+
+import java.util.function.Consumer;
+
+/**
+ * A particular type of {@link Transition} that follows the laws of the UAM (Uniformly Accelerated Motion)
+ * to animate a target and make it look like it is decelerating towards the end of the animation.
+ * <p></p>
+ * A bit of terminology and explanations:
+ * <p> - The {@code momentum} is the initial velocity of the animation, the speed at which the target will progress towards
+ * the end at the start of the animation. This velocity is not constant though as it is decreased every frame by the
+ * deceleration(negative acceleration) property.
+ * <p> - The {@code acceleration} is always a negative value since this motion in particular is a UDM (Uniformly Decelerated Motion),
+ * hence the terms acceleration and deceleration mean the same thing is this class. Every frame the momentum described above
+ * is diminished by the computed or given deceleration, this makes it look like the target is deceleration towards the end.
+ * <p> - The {@code displacement} is the difference between the end value and the start value. In an example let's say
+ * a Rectangle is at x coordinate 100, and we want it to move to x coordinate 300. The displacement is given by Xf - Xi,
+ * 300 - 100 = 200; The displacement is always a positive number, this class will automatically correct it if a negative number is given.
+ * <p></p>
+ * It is indeed possible to set an {@link Interpolator} to influence the progression of the animation.
+ * <p></p>
+ * Each frame the progression (relative to each frame) is computed and given to the specified {@link #getOnUpdate()} consumer.
+ * <p>
+ * To make things more clear let's see an example with the aforementioned Rectangle:
+ * <pre>
+ * {@code
+ *
+ * // We assume that the Rectangle is at Xi = 100 because of a translateX,
+ * // therefore what we want to animate is the translateX property.
+ * // We also assume that we want to move the Rectangle every time we detect a SCROLL event (but it could be everything,
+ * // the concept remains the same)
+ *
+ * Rectangle rt = new ...;
+ * pane.addEventHandler(ScrollEvent.SCROLL, e -> {
+ *     // Every scroll we start a new MomentumTransition
+ *     // I will use the fromTime(...) static method which makes things easier,
+ *     // but you can also use the fromDeceleration(...) static method if you want a constant deceleration,
+ *     // or specify all the parameters with the constructor (not recommended unless you really know what you are dealing with)
+ *     // The Rectangle will move of 20 pixels every scroll and the animation will last 500 milliseconds
+ *     MomentumTransition mt = MomentumTransition.fromTime(20, 500);
+ *     mt.setOnUpdate(delta -> rt.setTranslateX(rt.getTranslateX() + delta));
+ *     mt.setInterpolator(...); // Optional
+ *     mt.play();
+ * })
+ * }
+ * </pre>
+ * <p></p>
+ * A little side note: if you try to debug the values before and after the transition you may notice that the target
+ * value may be a little different. MomentumTransition is not 100% precise in the calculations and this is also needed
+ * to make the transition look smooth, I'm talking about just some decimals nothing too big.
+ * There are ways to make it precise tough.
+ * <p>
+ * You could track the target is an external variable that is not modified by the transition but from the action that leads
+ * to the transition. Then in the update consumer (setOnUpdate(delta -> {...}) you can compute the new value and clamp it
+ * with Math.min(...) or Math.max(...) so that it cannot go above/below the desired target.
+ * <p>
+ * Example:
+ * <pre>
+ * {@code
+ * // I'll use the Rectangle example again... let's initialize the target with the current position
+ * double target = 100.0;
+ *
+ * Rectangle rt = new ...;
+ * pane.addEventHandler(ScrollEvent.SCROLL, e -> {
+ *     // Increase target by displacement
+ *     target += 20;
+ *
+ *     MomentumTransition mt = MomentumTransition.fromTime(20, 500);
+ *     mt.setOnUpdate(delta -> {
+ *        double val = rt.getTranslateX() + delta;
+ *        double clamped = Math.min(val, target); // We don't want it to exceed the target
+ *        rt.setTranslateX(clamped);
+ *     });
+ *     mt.setInterpolator(...); // Optional
+ *     mt.play();
+ * }
+ * }
+ * </pre>
+ */
+public class MomentumTransition extends Transition {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private double momentum;
+	private double acceleration;
+	private double displacement;
+
+	private double displacementDelta;
+	private double lastFrameTime;
+	private Consumer<Double> onUpdate = delta -> {
+	};
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected MomentumTransition() {
+	}
+
+	public MomentumTransition(double momentum, double acceleration, double displacement) {
+		assert acceleration < 0;
+		this.momentum = momentum;
+		this.acceleration = acceleration;
+		this.displacement = Math.abs(displacement);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * Builds a {@code MomentumTransition} given the displacement and the duration of the animation.
+	 * <p>
+	 * The momentum and the deceleration are computed automatically by using {@link #timeToMomentum(double, double)}
+	 * and {@link #mtToDeceleration(double, double)}.
+	 */
+	public static MomentumTransition fromTime(double displacement, double millis) {
+		MomentumTransition mt = new MomentumTransition();
+		double absDisplacement = Math.abs(displacement);
+		mt.displacement = absDisplacement;
+		mt.setCycleDuration(Duration.millis(millis));
+		mt.momentum = timeToMomentum(absDisplacement, millis);
+		mt.acceleration = mtToDeceleration(mt.momentum, millis);
+		return mt;
+	}
+
+	/**
+	 * Builds a {@code MomentumTransition} given the displacement and the deceleration.
+	 * <p>
+	 * The momentum and the duration of the animation are computed automatically by using {@link #decelerationToMomentum(double, double)}
+	 * and {@link #mdToTime(double, double)}.
+	 * <p></p>
+	 * Please note that the {@code deceleration} param must be a negative number.
+	 */
+	public static MomentumTransition fromDeceleration(double displacement, double deceleration) {
+		assert deceleration < 0;
+		MomentumTransition mt = new MomentumTransition();
+		double absDisplacement = Math.abs(displacement);
+		mt.displacement = absDisplacement;
+		mt.acceleration = deceleration;
+		mt.momentum = decelerationToMomentum(absDisplacement, deceleration);
+		mt.setCycleDuration(Duration.millis(mdToTime(mt.momentum, deceleration)));
+		return mt;
+	}
+
+	/**
+	 * Given the displacement and the time, computes the momentum.
+	 * <p></p>
+	 * Formula: {@code (2 * displacement) / time}
+	 */
+	public static double timeToMomentum(double displacement, double time) {
+		return (2 * displacement) / time;
+	}
+
+	/**
+	 * Given the momentum and duration, computes the deceleration.
+	 * <p></p>
+	 * Formula: {@code -(momentum / time)}
+	 */
+	public static double mtToDeceleration(double momentum, double time) {
+		return -(momentum / time);
+	}
+
+	/**
+	 * Given the displacement and the deceleration, computes the momentum.
+	 * <p></p>
+	 * Formula: {@code Math.sqrt(-2 * deceleration * displacement)}
+	 */
+	public static double decelerationToMomentum(double displacement, double deceleration) {
+		return Math.sqrt(-2 * deceleration * displacement);
+	}
+
+	/**
+	 * Given the momentum and the deceleration, computes the duration.
+	 * <p></p>
+	 * Formula: {@code -(momentum / deceleration)}
+	 */
+	public static double mdToTime(double momentum, double deceleration) {
+		return -(momentum / deceleration);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	protected void interpolate(double frac) {
+		double deltaFrameTime = getDeltaFrameTime();
+		displacementDelta = momentum * deltaFrameTime;
+		momentum += acceleration * deltaFrameTime;
+		update();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Runs every frame to call the {@link #getOnUpdate()} consumer.
+	 */
+	public void update() {
+		if (onUpdate != null) onUpdate.accept(displacementDelta);
+	}
+
+	/**
+	 * Computes the difference between the current frame time and the last frame time.
+	 */
+	private double getDeltaFrameTime() {
+		double frameTime = getCurrentTime().toMillis();
+		double deltaFrameTime = frameTime - lastFrameTime;
+		lastFrameTime = frameTime;
+		return deltaFrameTime;
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * Allows to set the interpolator of this animation by using one of the ones provided by
+	 * the class {@link Interpolators}.
+	 */
+	public void setInterpolator(Interpolators interpolator) {
+		setInterpolator(interpolator.toInterpolator());
+	}
+
+	/**
+	 * @return the momentum of the transition
+	 */
+	public double getMomentum() {
+		return momentum;
+	}
+
+	/**
+	 * @return the acceleration of the transition
+	 */
+	public double getAcceleration() {
+		return acceleration;
+	}
+
+	/**
+	 * @return the displacement of the transition
+	 */
+	public double getDisplacement() {
+		return displacement;
+	}
+
+	/**
+	 * @return the action that runs every frame of the animation. The {@link Consumer}
+	 * carries the progress made during the last frame (relative to the given displacement)
+	 */
+	public Consumer<Double> getOnUpdate() {
+		return onUpdate;
+	}
+
+	/**
+	 * @see #getOnUpdate()
+	 */
+	public void setOnUpdate(Consumer<Double> onUpdate) {
+		this.onUpdate = onUpdate;
+	}
+}

+ 69 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/TriConsumer.java

@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * Represents an operation that accepts three input arguments and returns no
+ * result. This is the tri-arity specialization of {@link Consumer}.
+ * Unlike most other functional interfaces, {@code TriConsumer} is expected
+ * to operate via side effects.
+ *
+ * <p>This is a <a href="package-summary.html">functional interface</a>
+ * whose functional method is {@link #accept(Object, Object, Object)}.
+ *
+ * @param <A> the type of the first argument to the operation
+ * @param <B> the type of the second argument to the operation
+ * @param <C> the type of the third argument to the operation
+ */
+@FunctionalInterface
+public interface TriConsumer<A, B, C> {
+
+	/**
+	 * Performs this operation on the given arguments.
+	 *
+	 * @param a the first input argument
+	 * @param b the second input argument
+	 * @param c the third input argument
+	 */
+	void accept(A a, B b, C c);
+
+	/**
+	 * Returns a composed {@code TriConsumer} that performs, in sequence, this
+	 * operation followed by the {@code after} operation. If performing either
+	 * operation throws an exception, it is relayed to the caller of the
+	 * composed operation. If performing this operation throws an exception,
+	 * the {@code after} operation will not be performed.
+	 *
+	 * @param after the operation to perform after this operation
+	 * @return a composed {@code TriConsumer} that performs in sequence this
+	 * operation followed by the {@code after} operation
+	 * @throws NullPointerException if {@code after} is null
+	 */
+	default TriConsumer<A, B, C> andThen(TriConsumer<? super A, ? super B, ? super C> after) {
+		Objects.requireNonNull(after);
+
+		return (a, b, c) -> {
+			accept(a, b, c);
+			after.accept(a, b, c);
+		};
+	}
+}

+ 47 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/TriFunction.java

@@ -0,0 +1,47 @@
+package io.github.palexdev.mfxcore.base;
+
+import java.util.Objects;
+import java.util.function.Function;
+
+/**
+ * Represents a function that accepts three arguments and produces a result.
+ *
+ * <p>This is a <a href="package-summary.html">functional interface</a>
+ * whose functional method is {@link #apply(Object, Object, Object)}.
+ *
+ * @param <T> the type of the first argument to the function
+ * @param <U> the type of the second argument to the function
+ * @param <V> the type of the third argument to the function
+ * @param <R> the type of the result of the function
+ */
+@FunctionalInterface
+public interface TriFunction<T, U, V, R> {
+
+	/**
+	 * Applies this function to the given arguments.
+	 *
+	 * @param t the first function argument
+	 * @param u the second function argument
+	 * @param v the third function argument
+	 * @return the function result
+	 */
+	R apply(T t, U u, V v);
+
+	/**
+	 * Returns a composed function that first applies this function to
+	 * its input, and then applies the {@code after} function to the result.
+	 * If evaluation of either function throws an exception, it is relayed to
+	 * the caller of the composed function.
+	 *
+	 * @param <X>   the type of output of the {@code after} function, and of the
+	 *              composed function
+	 * @param after the function to apply after this function is applied
+	 * @return a composed function that first applies this function and then
+	 * applies the {@code after} function
+	 * @throws NullPointerException if after is null
+	 */
+	default <X> TriFunction<T, U, V, X> andThen(Function<? super R, ? extends X> after) {
+		Objects.requireNonNull(after);
+		return (t, u, v) -> after.apply(apply(t, u, v));
+	}
+}

+ 60 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/Alignment.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.geometry.HPos;
+import javafx.geometry.VPos;
+
+/**
+ * This immutable bean's purpose is to allow specifying positions based on
+ * {@link HPos} and {@link VPos} enumerations.
+ */
+public class Alignment {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final HPos hPos;
+	private final VPos vPos;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public Alignment(HPos hPos, VPos vPos) {
+		this.hPos = hPos;
+		this.vPos = vPos;
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+	public static Alignment of(HPos hPos, VPos vPos) {
+		return new Alignment(hPos, vPos);
+	}
+
+	//================================================================================
+	// Getters
+	//================================================================================
+	public HPos getHPos() {
+		return hPos;
+	}
+
+	public VPos getVPos() {
+		return vPos;
+	}
+}

+ 79 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/AnimationsData.java

@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.Node;
+import javafx.util.Duration;
+
+/**
+ * Simple immutable bean that has a node reference, a duration for the animation and
+ * an action to perform when the animation ends.
+ */
+public class AnimationsData {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final Node node;
+	private final Duration duration;
+	private final EventHandler<ActionEvent> onFinished;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public AnimationsData(Node node, Duration duration, EventHandler<ActionEvent> onFinished) {
+		this.node = node;
+		this.duration = duration;
+		this.onFinished = onFinished;
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	public Node getNode() {
+		return node;
+	}
+
+	public Duration getDuration() {
+		return duration;
+	}
+
+	public EventHandler<ActionEvent> getOnFinished() {
+		return onFinished;
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * Builds a new AnimationsData object with the given node and duration, the action is set to null.
+	 */
+	public static AnimationsData of(Node node, Duration duration) {
+		return of(node, duration, null);
+	}
+
+	/**
+	 * Builds a new AnimationsData object with the given node and duration and action.
+	 */
+	public static AnimationsData of(Node node, Duration duration, EventHandler<ActionEvent> onFinished) {
+		return new AnimationsData(node, duration, onFinished);
+	}
+}

+ 62 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/BiPredicateBean.java

@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import java.util.function.BiPredicate;
+
+/**
+ * A simple immutable bean that wraps a {@link BiPredicate} and a String that represents
+ * the name for the predicate.
+ * <p></p>
+ * Note that the {@link #toString()} method has been overridden to return the given name.
+ *
+ * @param <T> the type of the first predicate's argument
+ * @param <U> the type of the second predicate's argument
+ */
+public class BiPredicateBean<T, U> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final String name;
+	private final BiPredicate<T, U> predicate;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public BiPredicateBean(String name, BiPredicate<T, U> predicate) {
+		this.name = name;
+		this.predicate = predicate;
+	}
+
+	//================================================================================
+	// Getters
+	//================================================================================
+	public String getName() {
+		return name;
+	}
+
+	public BiPredicate<T, U> getPredicate() {
+		return predicate;
+	}
+
+	@Override
+	public String toString() {
+		return name;
+	}
+}

+ 114 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/CustomBounds.java

@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.geometry.BoundingBox;
+import javafx.geometry.Bounds;
+
+/**
+ * JavaFX allows you to create custom {@code Bounds} objects, see {@link BoundingBox}, the thing is
+ * that it automatically computes the max X/Y/Z values. This can be quite unfortunate in some rare
+ * cases because maybe you need some kind of special bounds, this bean is specifically for such edge cases.
+ */
+public class CustomBounds {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final double minX;
+	private final double minY;
+	private final double minZ;
+	private final double maxX;
+	private final double maxY;
+	private final double maxZ;
+	private final double width;
+	private final double height;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public CustomBounds(double minX, double minY, double maxX, double maxY, double width, double height) {
+		this(minX, minY, 0, maxX, maxY, 0, width, height);
+	}
+
+	public CustomBounds(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, double width, double height) {
+		this.minX = minX;
+		this.minY = minY;
+		this.minZ = minZ;
+		this.maxX = maxX;
+		this.maxY = maxY;
+		this.maxZ = maxZ;
+		this.width = width;
+		this.height = height;
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * @return a copy of the given {@link Bounds} object as a {@code CustomBounds} object.
+	 */
+	public static CustomBounds from(Bounds bounds) {
+		return new CustomBounds(
+				bounds.getMinX(),
+				bounds.getMinY(),
+				bounds.getMinZ(),
+				bounds.getMaxX(),
+				bounds.getMaxY(),
+				bounds.getMaxY(),
+				bounds.getWidth(),
+				bounds.getHeight()
+		);
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+	public double getMinX() {
+		return minX;
+	}
+
+	public double getMinY() {
+		return minY;
+	}
+
+	public double getMinZ() {
+		return minZ;
+	}
+
+	public double getMaxX() {
+		return maxX;
+	}
+
+	public double getMaxY() {
+		return maxY;
+	}
+
+	public double getMaxZ() {
+		return maxZ;
+	}
+
+	public double getWidth() {
+		return width;
+	}
+
+	public double getHeight() {
+		return height;
+	}
+}

+ 123 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/FilterBean.java

@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import io.github.palexdev.mfxcore.enums.ChainMode;
+import io.github.palexdev.mfxcore.filter.base.AbstractFilter;
+
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
+
+/**
+ * A simple bean that has all the necessary information to produce a {@link Predicate}
+ * for a given T object type.
+ * <p></p>
+ * It wraps the following data:
+ * <p> - A String which is the query
+ * <p> - An object of type {@link AbstractFilter}, which is effectively responsible for producing the {@link Predicate}
+ * <p> - A {@link BiPredicateBean}, which is used by {@link AbstractFilter}, see {@link AbstractFilter#predicateFor(String)} or {@link AbstractFilter#predicateFor(String, BiPredicate)}
+ * <p> - A {@link ChainMode} enumeration to specify how this filter should be combined with other filters
+ *
+ * @param <T> the type of objects to filter
+ * @param <U> the type of objects on which the {@link BiPredicate} operates
+ */
+public class FilterBean<T, U> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final String query;
+	private final AbstractFilter<T, U> filter;
+	private final BiPredicateBean<U, U> predicateBean;
+	private ChainMode mode;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public FilterBean(String query, AbstractFilter<T, U> filter, BiPredicateBean<U, U> predicateBean) {
+		this(query, filter, predicateBean, ChainMode.OR);
+	}
+
+	public FilterBean(String query, AbstractFilter<T, U> filter, BiPredicateBean<U, U> predicateBean, ChainMode mode) {
+		this.query = query;
+		this.filter = filter;
+		this.predicateBean = predicateBean;
+		this.mode = mode;
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Calls {@link AbstractFilter#predicateFor(String)} with the query specified by this bean.
+	 */
+	public Predicate<T> predicate() {
+		return filter.predicateFor(query);
+	}
+
+	/**
+	 * @return the query, see {@link AbstractFilter} documentation for more info about the query
+	 */
+	public String getQuery() {
+		return query;
+	}
+
+	/**
+	 * @return the {@link AbstractFilter} specified by this bean
+	 */
+	public AbstractFilter<T, U> getFilter() {
+		return filter;
+	}
+
+	/**
+	 * Delegate for {@link AbstractFilter#name()}.
+	 */
+	public String getFilterName() {
+		return filter.name();
+	}
+
+	/**
+	 * @return the {@link BiPredicateBean} specified by this bean
+	 */
+	public BiPredicateBean<U, U> getPredicateBean() {
+		return predicateBean;
+	}
+
+	/**
+	 * Delegate for {@link BiPredicateBean#getName()}.
+	 */
+	public String getPredicateName() {
+		return predicateBean.getName();
+	}
+
+	/**
+	 * @return the {@link ChainMode} enumeration that specifies how this filter should be chained with other filters.
+	 */
+	public ChainMode getMode() {
+		return mode;
+	}
+
+	/**
+	 * Sets the chain mode to the specified one.
+	 */
+	public void setMode(ChainMode mode) {
+		this.mode = mode;
+	}
+}
+

+ 110 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/Position.java

@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+
+import java.util.Objects;
+
+/**
+ * Simple bean that keeps track of two coordinates, x and y.
+ * <p>
+ * Both are JavaFX properties to allow dynamic uses.
+ */
+public class Position {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final DoubleProperty x = new SimpleDoubleProperty(0);
+	private final DoubleProperty y = new SimpleDoubleProperty(0);
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public Position() {
+	}
+
+	public Position(double x, double y) {
+		setX(x);
+		setY(y);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+	public static Position of(double x, double y) {
+		return new Position(x, y);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		Position that = (Position) o;
+		return getX() == (that.getX()) && getY() == (that.getY());
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(getX(), getY());
+	}
+
+	@Override
+	public String toString() {
+		return "X|Y (" + getX() + "; " + getY() + ")";
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	public double getX() {
+		return x.get();
+	}
+
+	/**
+	 * The x coordinate property.
+	 */
+	public DoubleProperty xProperty() {
+		return x;
+	}
+
+	public void setX(double xPosition) {
+		this.x.set(xPosition);
+	}
+
+	public double getY() {
+		return y.get();
+	}
+
+	/**
+	 * The y coordinate property
+	 */
+	public DoubleProperty yProperty() {
+		return y;
+	}
+
+	public void setY(double yPosition) {
+		this.y.set(yPosition);
+	}
+}
+

+ 102 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/PositionTransition.java

@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.animation.Transition;
+
+/**
+ * This is an extension of {@link Position} to be used
+ * with {@link Transition}s that start from a point P(x, y) and
+ * end at a point P1(endX, endY).
+ * <p></p>
+ * A very basic example:
+ * <p>
+ * Let's say I want to move a point P from (x, y) to the left
+ * (x1, y) with an animation. The transition would probably look like this:
+ * <pre>
+ * {@code
+ *     double startX = ...;
+ *     double startY = ...;
+ *     double endX = ...;
+ *     double endY = startY; // The y coordinate doesn't change so it is equal to the start one
+ *     TransitionPositionBean position = TransitionPositionBean.of(startX, startY, endX, endY);
+ *     Transition move = new Transition() {
+ *             @Override
+ *             protected void interpolate(double frac) {
+ *                 p.setX(x - position.deltaX() * frac);
+ *             }
+ *      }
+ * }
+ * </pre>
+ */
+public class PositionTransition extends Position {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final double endX;
+	private final double endY;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public PositionTransition(double x, double y, double endX, double endY) {
+		super(x, y);
+		this.endX = endX;
+		this.endY = endY;
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+	public static PositionTransition of(double x, double y, double endX, double endY) {
+		return new PositionTransition(x, y, endX, endY);
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * @return the end x coordinate
+	 */
+	public double getEndX() {
+		return endX;
+	}
+
+	/**
+	 * @return the end y coordinate
+	 */
+	public double getEndY() {
+		return endY;
+	}
+
+	/**
+	 * @return the difference between the star x and end x coordinates
+	 */
+	public double deltaX() {
+		return getX() - getEndX();
+	}
+
+	/**
+	 * @return the difference between the start y and end y coordinates
+	 */
+	public double deltaY() {
+		return getY() - getEndY();
+	}
+}

+ 99 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/Size.java

@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+
+import java.util.Objects;
+
+/**
+ * This bean contains two {@link DoubleProperty} to keep track/specify the sizes of something
+ * in terms of width and height.
+ */
+public class Size {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final DoubleProperty width = new SimpleDoubleProperty(0.0);
+	private final DoubleProperty height = new SimpleDoubleProperty(0.0);
+
+	//================================================================================
+	// Constructor
+	//================================================================================
+	public Size(double width, double height) {
+		setWidth(width);
+		setHeight(height);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+	public static Size of(double width, double height) {
+		return new Size(width, height);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		Size size = (Size) o;
+		return getWidth() == (size.getWidth()) && getHeight() == (size.getHeight());
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(getWidth(), getHeight());
+	}
+
+	@Override
+	public String toString() {
+		return "W x H (" + getWidth() + " x " + getHeight() + ")";
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+	public double getWidth() {
+		return width.get();
+	}
+
+	public DoubleProperty widthProperty() {
+		return width;
+	}
+
+	public void setWidth(double width) {
+		this.width.set(width);
+	}
+
+	public double getHeight() {
+		return height.get();
+	}
+
+	public DoubleProperty heightProperty() {
+		return height;
+	}
+
+	public void setHeight(double height) {
+		this.height.set(height);
+	}
+}

+ 49 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/SnapshotWrapper.java

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans;
+
+import javafx.scene.Node;
+import javafx.scene.SnapshotParameters;
+import javafx.scene.image.ImageView;
+import javafx.scene.image.WritableImage;
+import javafx.scene.paint.Color;
+
+/**
+ * Class used in various controls as a workaround for showing a node two or more times on the scene graph.
+ * <p>
+ * Makes a screenshot of a node with transparent background.
+ * Then {@link #getGraphic()} should be used to get an {@code ImageView} node which contains the screenshot.
+ * <p></p>
+ * A little side note: since it is a screenshot the image may appear a little blurry compared to the real
+ * graphic, however it should be acceptable and I believe this is still better than having no graphic at all.
+ */
+public class SnapshotWrapper {
+	private final WritableImage snapshot;
+
+	public SnapshotWrapper(Node node) {
+		SnapshotParameters snapshotParameters = new SnapshotParameters();
+		snapshotParameters.setFill(Color.TRANSPARENT);
+		snapshotParameters.setDepthBuffer(true);
+		snapshot = node.snapshot(snapshotParameters, null);
+	}
+
+	public Node getGraphic() {
+		return new ImageView(snapshot);
+	}
+}

+ 110 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/DoubleRange.java

@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans.range;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implementation of {@link NumberRange} to represent a Double range.
+ */
+public class DoubleRange extends NumberRange<Double> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public DoubleRange(Double min, Double max) {
+		super(min, max);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * @return a new instance of {@code DoubleRange} with the given min and max bounds.
+	 */
+	public static DoubleRange of(Double min, Double max) {
+		return new DoubleRange(min, max);
+	}
+
+	/**
+	 * @return a new instance of {@code DoubleRange} with the given val as both min and max bounds.
+	 */
+	public static DoubleRange of(Double val) {
+		return new DoubleRange(val, val);
+	}
+
+	/**
+	 * Checks if the given value is contained in the given range (bounds are included).
+	 */
+	public static boolean inRangeOf(double val, DoubleRange range) {
+		return Math.max(range.getMin(), val) == Math.min(val, range.getMax());
+	}
+
+	/**
+	 * Expands a range of doubles to a {@code List} with the given step.
+	 */
+	public static List<Double> expandRange(DoubleRange range, double step) {
+		List<Double> l = new ArrayList<>();
+		double start = range.getMin();
+		do {
+			l.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return l;
+	}
+
+	/**
+	 * Expands a range of doubles to a {@code Set} with the given step.
+	 * <p>
+	 * The {@code Set} is ordered.
+	 */
+	public static Set<Double> expandRangeToSet(DoubleRange range, double step) {
+		Set<Double> s = new LinkedHashSet<>();
+		double start = range.getMin();
+		do {
+			s.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return s;
+	}
+
+	/**
+	 * Expands a range of double to an array.
+	 */
+	public static Double[] expandRangeToArray(double min, double max, double step) {
+		return expandRange(of(min, max), step).toArray(Double[]::new);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public Double sum() {
+		return getMin() + getMax();
+	}
+
+	@Override
+	public Double diff() {
+		return getMax() - getMin();
+	}
+}

+ 110 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/FloatRange.java

@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans.range;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implementation of {@link NumberRange} to represent a Float range.
+ */
+public class FloatRange extends NumberRange<Float> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public FloatRange(Float min, Float max) {
+		super(min, max);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * @return a new instance of {@code FloatRange} with the given min and max bounds.
+	 */
+	public static FloatRange of(Float min, Float max) {
+		return new FloatRange(min, max);
+	}
+
+	/**
+	 * @return a new instance of {@code FloatRange} with the given val as both min and max bounds.
+	 */
+	public static FloatRange of(Float val) {
+		return new FloatRange(val, val);
+	}
+
+	/**
+	 * Checks if the given value is contained in the given range (bounds are included).
+	 */
+	public static boolean inRangeOf(float val, FloatRange range) {
+		return Math.max(range.getMin(), val) == Math.min(val, range.getMax());
+	}
+
+	/**
+	 * Expands a range of floats to a {@code List} with the given step.
+	 */
+	public static List<Float> expandRange(FloatRange range, float step) {
+		List<Float> l = new ArrayList<>();
+		float start = range.getMin();
+		do {
+			l.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return l;
+	}
+
+	/**
+	 * Expands a range of floats to a {@code Set} with the given step.
+	 * <p>
+	 * The {@code Set} is ordered.
+	 */
+	public static Set<Float> expandRangeToSet(FloatRange range, float step) {
+		Set<Float> s = new LinkedHashSet<>();
+		float start = range.getMin();
+		do {
+			s.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return s;
+	}
+
+	/**
+	 * Expands a range of floats to an array.
+	 */
+	public static Float[] expandRangeToArray(float min, float max, float step) {
+		return expandRange(of(min, max), step).toArray(Float[]::new);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public Float sum() {
+		return getMin() + getMax();
+	}
+
+	@Override
+	public Float diff() {
+		return getMax() - getMin();
+	}
+}

+ 129 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/IntegerRange.java

@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans.range;
+
+import java.util.*;
+import java.util.stream.IntStream;
+
+/**
+ * Implementation of {@link NumberRange} to represent an Integer range.
+ */
+public class IntegerRange extends NumberRange<Integer> implements Iterable<Integer> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public IntegerRange(Integer min, Integer max) {
+		super(min, max);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * @return a new instance of {@code IntegerRange} with the given min and max bounds.
+	 */
+	public static IntegerRange of(Integer min, Integer max) {
+		return new IntegerRange(min, max);
+	}
+
+	/**
+	 * @return a new instance of {@code IntegerRange} with the given val as both min and max bounds.
+	 */
+	public static IntegerRange of(Integer val) {
+		return new IntegerRange(val, val);
+	}
+
+	/**
+	 * Checks if the given value is contained in the given range (bounds are included).
+	 */
+	public static boolean inRangeOf(int val, IntegerRange range) {
+		return Math.max(range.getMin(), val) == Math.min(val, range.getMax());
+	}
+
+	/**
+	 * Expands a range of integers to a {@code List} with step=1.
+	 */
+	public static List<Integer> expandRange(IntegerRange range) {
+		return IntStream.rangeClosed(range.getMin(), range.getMax()).collect(ArrayList::new, List::add, List::addAll);
+	}
+
+	/**
+	 * Expands a range of integers to a {@code List} with the given step.
+	 */
+	public static List<Integer> expandRange(IntegerRange range, int step) {
+		List<Integer> l = new ArrayList<>();
+		int start = range.getMin();
+		do {
+			l.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return l;
+	}
+
+	/**
+	 * Expands a range of integers to a {@code Set} with step=1.
+	 * <p>
+	 * The {@code Set} is ordered.
+	 */
+	public static Set<Integer> expandRangeToSet(IntegerRange range) {
+		return IntStream.rangeClosed(range.getMin(), range.getMax()).collect(LinkedHashSet::new, Set::add, Set::addAll);
+	}
+
+	/**
+	 * Expands a range of integers to a {@code Set} with the given step.
+	 * <p>
+	 * The {@code Set} is ordered.
+	 */
+	public static Set<Integer> expandRangeToSet(IntegerRange range, int step) {
+		Set<Integer> s = new LinkedHashSet<>();
+		int start = range.getMin();
+		do {
+			s.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return s;
+	}
+
+	/**
+	 * Expands a range of integers to an array.
+	 */
+	public static Integer[] expandRangeToArray(int min, int max) {
+		return expandRange(of(min, max)).toArray(Integer[]::new);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public Integer sum() {
+		return getMin() + getMax();
+	}
+
+	@Override
+	public Integer diff() {
+		return getMax() - getMin();
+	}
+
+	@Override
+	public PrimitiveIterator.OfInt iterator() {
+		return IntStream.rangeClosed(getMin(), getMax()).iterator();
+	}
+}

+ 113 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/LongRange.java

@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans.range;
+
+import java.util.*;
+import java.util.stream.LongStream;
+
+/**
+ * Implementation of {@link NumberRange} to represent a Long range.
+ */
+public class LongRange extends NumberRange<Long> implements Iterable<Long> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public LongRange(Long min, Long max) {
+		super(min, max);
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+
+	/**
+	 * @return a new instance of {@code LongRange} with the given min and max bounds.
+	 */
+	public static LongRange of(Long min, Long max) {
+		return new LongRange(min, max);
+	}
+
+	/**
+	 * @return a new instance of {@code LongRange} with the given val as both min and max bounds.
+	 */
+	public static LongRange of(Long val) {
+		return new LongRange(val, val);
+	}
+
+	/**
+	 * Checks if the given value is contained in the given range (bounds are included).
+	 */
+	public static boolean inRangeOf(long val, LongRange range) {
+		return Math.max(range.getMin(), val) == Math.min(val, range.getMax());
+	}
+
+	/**
+	 * Expands a range of longs to a {@code List} with the given step.
+	 */
+	public static List<Long> expandRange(LongRange range, long step) {
+		List<Long> l = new ArrayList<>();
+		long start = range.getMin();
+		do {
+			l.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return l;
+	}
+
+	/**
+	 * Expands a range of longs to a {@code Set} with the given step.
+	 * <p>
+	 * The {@code Set} is ordered.
+	 */
+	public static Set<Long> expandRangeToSet(LongRange range, long step) {
+		Set<Long> s = new LinkedHashSet<>();
+		long start = range.getMin();
+		do {
+			s.add(start);
+			start += step;
+		} while (start <= range.getMax());
+		return s;
+	}
+
+	/**
+	 * Expands a range of long to an array.
+	 */
+	public static Long[] expandRangeToArray(long min, long max, long step) {
+		return expandRange(of(min, max), step).toArray(Long[]::new);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public Long sum() {
+		return getMin() + getMax();
+	}
+
+	@Override
+	public Long diff() {
+		return getMax() - getMin();
+	}
+
+	@Override
+	public PrimitiveIterator.OfLong iterator() {
+		return LongStream.rangeClosed(getMin(), getMax()).iterator();
+	}
+}

+ 99 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/beans/range/NumberRange.java

@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.beans.range;
+
+import java.util.Objects;
+
+/**
+ * Base class to represent a range of numbers between a min and a max.
+ *
+ * @param <N> The type of Number to represent (must also be a {@link Comparable})
+ */
+public abstract class NumberRange<N extends Number & Comparable<N>> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final N min;
+	private final N max;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public NumberRange(N min, N max) {
+		if (min == null || max == null || min.compareTo(max) > 0) {
+			throw new IllegalArgumentException("Invalid range for values: Min[" + min + "], Max[" + max + "]");
+		}
+
+		this.min = min;
+		this.max = max;
+	}
+
+	//================================================================================
+	// Abstract Methods
+	//================================================================================
+
+	/**
+	 * @return the sum of {@link #getMin()} and {@link #getMax()}
+	 */
+	public abstract N sum();
+
+	/**
+	 * @return the difference between {@link #getMax()} and {@link #getMin()}
+	 */
+	public abstract N diff();
+
+	//================================================================================
+	// Getters
+	//================================================================================
+
+	/**
+	 * @return the lower bound
+	 */
+	public N getMin() {
+		return min;
+	}
+
+	/**
+	 * @return the upper bound
+	 */
+	public N getMax() {
+		return max;
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		NumberRange<?> that = (NumberRange<?>) o;
+		return getMin().equals(that.getMin()) && getMax().equals(that.getMax());
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(getMin(), getMax());
+	}
+
+	@Override
+	public String toString() {
+		return "Min[" + getMin() + "], Max[" + getMax() + "]";
+	}
+}

+ 173 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/AbstractBinding.java

@@ -0,0 +1,173 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.IBinding;
+import io.github.palexdev.mfxcore.enums.BindingState;
+import javafx.beans.value.ObservableValue;
+
+import java.util.Optional;
+
+/**
+ * Base class for all types of bindings, implements {@link IBinding}.
+ * <p>
+ * This abstract class allows to have common properties in one place (such as the {@code Target} and the state) but
+ * adds new features as well.
+ * <p></p>
+ * This defines a map of particular {@code Sources}, {@link ExternalSource}, which can be used to perform any operation
+ * when they change. However, they are intended to invalidate the binding when needed, in special occasions.
+ * <p></p>
+ * This also defines a series of {@link Runnable}s that allow to run operations before and after the aforementioned
+ * invalidations.
+ *
+ * @param <T> the type of the target's observable
+ */
+@SuppressWarnings("rawtypes")
+public abstract class AbstractBinding<T> implements IBinding<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	protected Target<T> target;
+	protected BindingState state = BindingState.NULL;
+	protected final WeakLinkedHashMap<ObservableValue, ExternalSource> invalidatingSources = new WeakLinkedHashMap<>();
+
+	protected Runnable beforeTargetInvalidation = () -> {
+	};
+	protected Runnable beforeSourceInvalidation = () -> {
+	};
+	protected Runnable afterTargetInvalidation = () -> {
+	};
+	protected Runnable afterSourceInvalidation = () -> {
+	};
+
+	//================================================================================
+	// Abstract Methods
+	//================================================================================
+
+	/**
+	 * Adds and activates the given {@link ExternalSource} to this binding.
+	 */
+	public abstract <S> AbstractBinding<T> addInvalidatingSource(ExternalSource<S> source);
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	@Override
+	public Target<T> getTarget() {
+		return target;
+	}
+
+	@Override
+	public BindingState state() {
+		return state;
+	}
+
+	/**
+	 * Shortcut for:
+	 * <pre>
+	 * {@code
+	 * addInvalidatingSource(new ExternalSource<>(source)
+	 *          .setAction((o, n) -> invalidate());
+	 * }
+	 * </pre>
+	 */
+	public <S> AbstractBinding<T> addTargetInvalidatingSource(ObservableValue<? extends S> source) {
+		return addInvalidatingSource(new ExternalSource<>(source).setAction((o, n) -> invalidate()));
+	}
+
+	/**
+	 * Shortcut for:
+	 * <pre>
+	 * {@code
+	 * addInvalidatingSource(new ExternalSource<>(source)
+	 *          .setAction((o, n) -> invalidateSource());
+	 * }
+	 * </pre>
+	 */
+	public <S> AbstractBinding<T> addSourcesInvalidatingSource(ObservableValue<? extends S> source) {
+		return addInvalidatingSource(new ExternalSource<>(source).setAction((o, n) -> invalidateSource()));
+	}
+
+	/**
+	 * Removes and disposes the given {@link ExternalSource} from this binding.
+	 */
+	public <S> AbstractBinding<T> removeInvalidatingSource(ObservableValue<? extends S> source) {
+		Optional.ofNullable(invalidatingSources.remove(source))
+				.ifPresent(ExternalSource::dispose);
+		return this;
+	}
+
+	/**
+	 * Calls {@link #removeInvalidatingSource(ObservableValue)} with {@link ExternalSource#getObservable()}.
+	 */
+	public <S> AbstractBinding<T> removeInvalidatingSource(ExternalSource<S> source) {
+		return removeInvalidatingSource(source.getObservable());
+	}
+
+	/**
+	 * Disposes and removes all the {@link ExternalSource}s from this binding.
+	 */
+	public AbstractBinding<T> clearInvalidatingSources() {
+		invalidatingSources.values().forEach(ExternalSource::dispose);
+		invalidatingSources.clear();
+		return this;
+	}
+
+	/**
+	 * @return the action performed before invalidating the target
+	 */
+	public Runnable getBeforeTargetInvalidation() {
+		return beforeTargetInvalidation;
+	}
+
+	/**
+	 * Sets the action to perform before invalidating the target.
+	 */
+	public AbstractBinding<T> setBeforeTargetInvalidation(Runnable beforeTargetInvalidation) {
+		this.beforeTargetInvalidation = beforeTargetInvalidation;
+		return this;
+	}
+
+	/**
+	 * @return the action performed before invalidating the source
+	 */
+	public Runnable getBeforeSourceInvalidation() {
+		return beforeSourceInvalidation;
+	}
+
+	/**
+	 * Sets the action to perform before invalidating the source.
+	 */
+	public AbstractBinding<T> setBeforeSourceInvalidation(Runnable beforeSourceInvalidation) {
+		this.beforeSourceInvalidation = beforeSourceInvalidation;
+		return this;
+	}
+
+	/**
+	 * @return the action performed after invalidating the target
+	 */
+	public Runnable getAfterTargetInvalidation() {
+		return afterTargetInvalidation;
+	}
+
+	/**
+	 * Sets the action to perform after invalidating the target.
+	 */
+	public AbstractBinding<T> setAfterTargetInvalidation(Runnable afterTargetInvalidation) {
+		this.afterTargetInvalidation = afterTargetInvalidation;
+		return this;
+	}
+
+	/**
+	 * @return the action performed after invalidating the source
+	 */
+	public Runnable getAfterSourceInvalidation() {
+		return afterSourceInvalidation;
+	}
+
+	/**
+	 * Sets the action to perform after invalidating the source.
+	 */
+	public AbstractBinding<T> setAfterSourceInvalidation(Runnable afterSourceInvalidation) {
+		this.afterSourceInvalidation = afterSourceInvalidation;
+		return this;
+	}
+}

+ 60 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/AbstractSource.java

@@ -0,0 +1,60 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.ISource;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Base class for all types of {@code Sources}, implements {@link ISource}.
+ * <p></p>
+ * This class allows to have common properties in one place (such as the source's observable and the target), but also
+ * implements common methods and defines methods that need to be used only internally.
+ *
+ * @param <S> the type of the source's observable
+ * @param <T> the type of the target's observable
+ */
+public abstract class AbstractSource<S, T> implements ISource<S, T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	protected ObservableValue<? extends S> observable;
+	protected Target<T> target;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected AbstractSource() {
+	}
+
+	public AbstractSource(ObservableValue<? extends S> observable) {
+		this.observable = observable;
+	}
+
+	//================================================================================
+	// Abstract Methods
+	//================================================================================
+
+	/**
+	 * Activates the source by adding the needed listeners.
+	 */
+	protected abstract void listen();
+
+	/**
+	 * Activates the source by adding the needed listeners, unlike {@link #listen()} this
+	 * is used by bidirectional biding, in fact a listener is also added to the given target
+	 * to trigger the target update when this changes.
+	 */
+	protected abstract void listen(Target<T> target);
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	@Override
+	public ObservableValue<? extends S> getObservable() {
+		return observable;
+	}
+
+	@Override
+	public S getValue() {
+		return observable.getValue();
+	}
+}

+ 205 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/BidirectionalBinding.java

@@ -0,0 +1,205 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.IBinding;
+import io.github.palexdev.mfxcore.base.bindings.base.ISource;
+import io.github.palexdev.mfxcore.enums.BindingState;
+import io.github.palexdev.mfxcore.enums.BindingType;
+import javafx.beans.value.ObservableValue;
+
+import java.util.Optional;
+
+/**
+ * Concrete implementation of {@link AbstractBinding} to define bidirectional bindings.
+ * <p></p>
+ * Bidirectional bindings can have multiple sources and multiple other sources, {@link ExternalSource},
+ * which should be used to invalidate the binding (either of target or sources) when needed, in special occasions.
+ * <p></p>
+ * Note that sources can use whatever source type you want as long as the source can correctly:
+ * <p> - produce values compatibles with the target when updating the target
+ * <p> - produce values compatibles with the source when the target changed
+ *
+ * @param <T> the binding's target type
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class BidirectionalBinding<T> extends AbstractBinding<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final WeakLinkedHashMap<ObservableValue, AbstractSource> sources = new WeakLinkedHashMap<>();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public BidirectionalBinding() {
+	}
+
+	public BidirectionalBinding(ObservableValue<? extends T> target) {
+		super.target = new Target<>(target);
+	}
+
+	public static <T> BidirectionalBinding<T> create() {
+		return new BidirectionalBinding<>();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Sets this binding's target.
+	 *
+	 * @throws IllegalStateException if the binding' state is {@link BindingState#BOUND}
+	 */
+	public BidirectionalBinding<T> target(ObservableValue<? extends T> observable) {
+		if (mayBeBound()) throw new IllegalStateException("Cannot set target as this binding is currently active");
+		super.target = new Target<>(observable);
+		return this;
+	}
+
+	/**
+	 * Adds all the given sources to this binding. If a given source was already present it is not
+	 * overwritten.
+	 */
+	@SafeVarargs
+	public final BidirectionalBinding<T> addSources(AbstractSource<?, T>... sources) {
+		for (AbstractSource<?, T> source : sources) {
+			addSource(source);
+		}
+		return this;
+	}
+
+	/**
+	 * Adds the given source to this binding. If the given source was already present it is not
+	 * overwritten.
+	 */
+	public <S> BidirectionalBinding<T> addSource(AbstractSource<S, T> source) {
+		if (sources.containsKey(source.getObservable())) return this;
+		sources.put(source.getObservable(), source);
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Before activating the binding checks if there are already unidirectional or bidirectional bindings registered
+	 * for the given target and eventually disposes them.
+	 * <p>
+	 * Then activates the all the sources with {@link AbstractSource#listen(Target)}, registers the binding in {@link MFXBindings}
+	 * and sets the state to {@link BindingState#BOUND}.
+	 *
+	 * @throws IllegalStateException if the binding has been disposed before OR the target is null
+	 *                               OR there are no sources
+	 */
+	@Override
+	public BidirectionalBinding<T> get() {
+		if (isDisposed())
+			throw new IllegalStateException("This binding has been previously disposed and cannot be used anymore");
+		if (target == null) throw new IllegalStateException("Cannot bind as target is null");
+		if (sources.isEmpty()) throw new IllegalStateException("No sources specifies for this binding");
+		MFXBindings bindings = MFXBindings.instance();
+
+		if (bindings.isBound(target)) {
+			bindings.getBinding(target).dispose();
+		}
+
+		if (bindings.isBoundBidirectional(target)) {
+			bindings.getBiBinding(target).dispose();
+		}
+
+		target.bindingType = BindingType.BIDIRECTIONAL;
+		sources.values().forEach(s -> s.listen(target));
+		bindings.addBinding(this);
+		state = BindingState.BOUND;
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * For bidirectional bindings the target is updated with the value from the last added
+	 * source. This is possible thanks to {@link WeakLinkedHashMap}, {@link WeakLinkedHashMap#getLastKey()}.
+	 * <p></p>
+	 * Also runs {@link #getBeforeTargetInvalidation()} and {@link #getAfterTargetInvalidation()}.
+	 */
+	@Override
+	public IBinding<T> invalidate() {
+		Optional.ofNullable(sources.getLastKey())
+				.map(sources::get)
+				.ifPresent(s -> {
+					beforeTargetInvalidation.run();
+					s.updateTarget(s.getValue(), s.getValue());
+					afterTargetInvalidation.run();
+				});
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Also runs {@link #getBeforeSourceInvalidation()} and {@link #getAfterSourceInvalidation()}.
+	 */
+	@Override
+	public IBinding<T> invalidateSource() {
+		beforeSourceInvalidation.run();
+		sources.values().forEach(s -> s.updateSource(target.getValue(), target.getValue()));
+		afterSourceInvalidation.run();
+		return this;
+	}
+
+	public <S> BidirectionalBinding<T> addInvalidatingSource(ExternalSource<S> source) {
+		source.listen();
+		invalidatingSources.put(source.getObservable(), source);
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Disposes all the sources and removes them, calls {@link #clearInvalidatingSources()},
+	 * sets the state to {@link BindingState#UNBOUND} then un-registers the binding from {@link MFXBindings}.
+	 */
+	@Override
+	public BidirectionalBinding<T> unbind() {
+		sources.values().forEach(ISource::dispose);
+		sources.clear();
+		clearInvalidatingSources();
+		state = BindingState.UNBOUND;
+		MFXBindings.instance().removeBinding(this);
+		return this;
+	}
+
+	/**
+	 * Disposes only the given source if present.
+	 * <p></p>
+	 * If that was the last source then the state is set to {@link BindingState#UNBOUND} and
+	 * the binding is un-registered from {@link MFXBindings}. Note that unlike {@link #unbind}
+	 * this won't dispose and remove the invalidating sources!
+	 */
+	public <S> BidirectionalBinding<T> unbind(ObservableValue<? extends S> source) {
+		AbstractSource s = sources.remove(source);
+		if (s != null) {
+			s.dispose();
+		}
+		if (sources.isEmpty()) {
+			// Note that invalidating sources will be kept
+			state = BindingState.UNBOUND;
+			MFXBindings.instance().removeBinding(this);
+		}
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Calls {@link #unbind()}.
+	 * <p>
+	 * Then sets the remaining properties to null and the state to {@link BindingState#DISPOSED}.
+	 */
+	@Override
+	public void dispose() {
+		unbind();
+		target.dispose();
+		target = null;
+		state = BindingState.DISPOSED;
+	}
+}

+ 203 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Binding.java

@@ -0,0 +1,203 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.IBinding;
+import io.github.palexdev.mfxcore.base.bindings.base.Updater;
+import io.github.palexdev.mfxcore.enums.BindingState;
+import io.github.palexdev.mfxcore.enums.BindingType;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Concrete implementation of {@link AbstractBinding} to define unidirectional bindings.
+ * <p></p>
+ * Unidirectional bindings have a single source and can have multiple other sources, {@link ExternalSource},
+ * which should be used to invalidate the binding when needed, in special occasions.
+ * <p>
+ * {@link #invalidateSource()} is unsupported as unidirectional bindings do not update their source.
+ * <p></p>
+ * Note that you can use whatever source you want as long as the source produces, when updating, values compatible
+ * with this binding's target type.
+ *
+ * @param <T> the binding's target type
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class Binding<T> extends AbstractBinding<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private AbstractSource source;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public Binding() {
+	}
+
+	public Binding(ObservableValue<? extends T> target, AbstractSource<?, ?> source) {
+		super.target = new Target<>(target);
+		this.source = source;
+	}
+
+	public static <T> Binding<T> create() {
+		return new Binding<>();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Sets this binding's target.
+	 *
+	 * @throws IllegalStateException if the binding' state is {@link BindingState#BOUND}
+	 */
+	public Binding<T> target(ObservableValue<? extends T> observable) {
+		if (mayBeBound()) throw new IllegalStateException("Cannot set target as this binding is currently active");
+		super.target = new Target<>(observable);
+		return this;
+	}
+
+	/**
+	 * Sets this binding's source, as no updater is given attempts to use {@link Updater#implicit(Target)}.
+	 *
+	 * @throws IllegalStateException if the binding' state is {@link BindingState#BOUND}
+	 */
+	public Binding<T> source(ObservableValue<? extends T> source) {
+		if (mayBeBound()) throw new IllegalStateException("Cannot set source as this binding is currently active");
+		this.source = new Source<>(source).setTargetUpdater(Updater.implicit(target));
+		return this;
+	}
+
+	/**
+	 * Sets this binding' source.
+	 *
+	 * @throws IllegalStateException if the binding' state is {@link BindingState#BOUND}
+	 */
+	public <S> Binding<T> source(AbstractSource<S, T> source) {
+		if (mayBeBound()) throw new IllegalStateException("Cannot set source as this binding is currently active");
+		this.source = source;
+		return this;
+	}
+
+	/**
+	 * Sets the binding' source from the given {@link Source.Builder}.
+	 *
+	 * @throws IllegalStateException if the binding' state is {@link BindingState#BOUND}
+	 */
+	public <S> Binding<T> source(Source.Builder<S> sBuilder) {
+		if (mayBeBound()) throw new IllegalStateException("Cannot set source as this binding is currently active");
+		this.source = sBuilder.get();
+		return this;
+	}
+
+	/**
+	 * Sets the binding' source from the given {@link MappingSource.Builder}.
+	 *
+	 * @throws IllegalStateException if the binding' state is {@link BindingState#BOUND}
+	 */
+	public <S> Binding<T> source(MappingSource.Builder<S, T> sBuilder) {
+		if (mayBeBound()) throw new IllegalStateException("Cannot set source as this binding is currently active");
+		this.source = sBuilder.get();
+		return this;
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Before activating the binding checks if there are already unidirectional or bidirectional bindings registered
+	 * for the given target and eventually disposes them.
+	 * <p>
+	 * Then activates the source with {@link AbstractSource#listen()}, registers the binding in {@link MFXBindings}
+	 * and sets the state to {@link BindingState#BOUND}.
+	 *
+	 * @throws IllegalStateException if the binding has been disposed before OR the target is null
+	 *                               OR the source is null
+	 */
+	@Override
+	public Binding<T> get() {
+		if (isDisposed())
+			throw new IllegalStateException("This binding has been previously disposed and cannot be used anymore");
+		if (target == null) throw new IllegalStateException("Cannot bind as target is null");
+		if (source == null) throw new IllegalStateException("Cannot bind as source is null");
+		MFXBindings bindings = MFXBindings.instance();
+
+		if (bindings.isBoundBidirectional(target)) {
+			bindings.getBiBinding(target).dispose();
+		}
+
+		if (mayBeBound() || bindings.isBound(target)) {
+			bindings.getBinding(target).dispose();
+		}
+
+		target.bindingType = BindingType.UNIDIRECTIONAL;
+		source.target = target;
+		source.listen();
+		bindings.addBinding(this);
+		state = BindingState.BOUND;
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Also runs {@link #getBeforeTargetInvalidation()} and {@link #getAfterTargetInvalidation()}.
+	 */
+	@Override
+	public Binding<T> invalidate() {
+		beforeTargetInvalidation.run();
+		source.updateTarget(source.getValue(), source.getValue());
+		afterTargetInvalidation.run();
+		return this;
+	}
+
+	/**
+	 * Unsupported.
+	 *
+	 * @throws UnsupportedOperationException unidirectional bindings cannot update their source
+	 */
+	@Override
+	public IBinding<T> invalidateSource() {
+		throw new UnsupportedOperationException("Unidirectional bindings cannot update their source");
+	}
+
+	@Override
+	public <S> Binding<T> addInvalidatingSource(ExternalSource<S> source) {
+		source.listen();
+		invalidatingSources.put(source.getObservable(), source);
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Disposes the source and sets it to null, calls {@link #clearInvalidatingSources()},
+	 * sets the state to {@link BindingState#UNBOUND} then un-registers the binding from {@link MFXBindings}.
+	 */
+	@Override
+	public Binding<T> unbind() {
+		source.dispose();
+		source = null;
+		clearInvalidatingSources();
+		state = BindingState.UNBOUND;
+		MFXBindings.instance().removeBinding(this);
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Calls {@link #unbind()}.
+	 * <p>
+	 * Then sets the remaining properties to null and the state to {@link BindingState#DISPOSED}.
+	 */
+	@Override
+	public void dispose() {
+		unbind();
+		target.dispose();
+		target = null;
+		state = BindingState.DISPOSED;
+	}
+}

+ 66 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/BooleanListBinding.java

@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.bindings;
+
+import javafx.beans.binding.BooleanBinding;
+import javafx.beans.property.BooleanProperty;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+
+/**
+ * A {@code BooleanListBinding} is a particular binding that takes a list of
+ * {@link BooleanProperty} and observes each one of them updating its value
+ * when they change. The value is true only when all properties are true, it's false
+ * when even only one of them is false.
+ */
+public class BooleanListBinding extends BooleanBinding {
+	private final ObservableList<BooleanProperty> boundList;
+	private final ListChangeListener<BooleanProperty> changeListener;
+	private BooleanProperty[] observedProperties;
+
+	public BooleanListBinding(ObservableList<BooleanProperty> boundList) {
+		this.boundList = boundList;
+		this.changeListener = c -> refreshBinding();
+		this.boundList.addListener(changeListener);
+		refreshBinding();
+	}
+
+	@Override
+	protected boolean computeValue() {
+		for (BooleanProperty bp : observedProperties) {
+			if (!bp.get()) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public void dispose() {
+		boundList.removeListener(changeListener);
+		super.dispose();
+	}
+
+	private void refreshBinding() {
+		super.unbind(observedProperties);
+		observedProperties = boundList.toArray(new BooleanProperty[0]);
+		super.bind(observedProperties);
+		this.invalidate();
+	}
+}

+ 135 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/ExternalSource.java

@@ -0,0 +1,135 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.Updater;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.value.ObservableValue;
+
+import java.util.Objects;
+
+/**
+ * Special type of {@code Source} whose function should be to invalidate a binding when this changes.
+ * <p>
+ * It's called {@code ExternalSource} because technically it has nothing to do with a binding, and the action performed
+ * can be anything. However, they are part of a {@link AbstractBinding} as they should perform operations that can
+ * influence the binding.
+ * <p>
+ * To be precise, this source allows you to define any action, but the intended way to use this is to
+ * trigger bindings invalidation (either of target or sources).
+ *
+ * @param <S> the type of the source's observable
+ */
+public class ExternalSource<S> extends AbstractSource<S, S> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private Updater<S> action = (oldValue, newValue) -> {
+	};
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected ExternalSource() {
+	}
+
+	public ExternalSource(ObservableValue<? extends S> observable) {
+		super(observable);
+	}
+
+	public ExternalSource(ObservableValue<? extends S> observable, Updater<S> action) {
+		super(observable);
+		this.action = action;
+	}
+
+	public static <S> ExternalSource<S> of(ObservableValue<? extends S> observable) {
+		return new ExternalSource<>(observable);
+	}
+
+	public static <S> ExternalSource<S> of(ObservableValue<? extends S> observable, Updater<S> action) {
+		return new ExternalSource<>(observable, action);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	// TODO check this documentation
+
+	/**
+	 * Activates this invalidating source by adding a listener to it that will trigger the specified {@link #getAction()}.
+	 */
+	@Override
+	protected void listen() {
+		When.onChanged(observable)
+				.then(action::update)
+				.listen();
+	}
+
+	/**
+	 * Unsupported.
+	 *
+	 * @throws UnsupportedOperationException {@code InvalidatingSources} do not operate on a target
+	 */
+	@Override
+	protected void listen(Target<S> target) {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Unsupported.
+	 *
+	 * @throws UnsupportedOperationException {@code InvalidatingSources} are not directly responsible for updating
+	 *                                       a target
+	 */
+	@Override
+	public void updateTarget(S oldValue, S newValue) {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Unsupported.
+	 *
+	 * @throws UnsupportedOperationException {@code InvalidatingSources} are not directly responsible for
+	 *                                       updating sources
+	 */
+	@Override
+	public void updateSource(S oldValue, S newValue) {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Disposes the source by using {@link When#disposeFor(ObservableValue)},
+	 * then sets the observable to null.
+	 */
+	@Override
+	public void dispose() {
+		When.disposeFor(observable);
+		observable = null;
+	}
+
+	/**
+	 * @return the action performed by this source when it changes
+	 */
+	public Updater<S> getAction() {
+		return action;
+	}
+
+	/**
+	 * Sets the action performed by this source whe int changes.
+	 */
+	public ExternalSource<S> setAction(Updater<S> action) {
+		this.action = action;
+		return this;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		ExternalSource<?> that = (ExternalSource<?>) o;
+		return observable.equals(that.observable);
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(observable);
+	}
+}

+ 398 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/MFXBindings.java

@@ -0,0 +1,398 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.IBinding;
+import javafx.beans.property.*;
+import javafx.beans.value.ObservableValue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.WeakHashMap;
+
+/**
+ * Utility class mainly used to track both {@link Binding}s and {@link BidirectionalBinding}s.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class MFXBindings {
+	//================================================================================
+	// Static Members
+	//================================================================================
+	private static final MFXBindings instance = new MFXBindings();
+
+	public static MFXBindings instance() {
+		return instance;
+	}
+
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final WeakHashMap<ObservableValue, Binding> bindings = new WeakHashMap<>();
+	private final WeakHashMap<ObservableValue, BidirectionalBinding> biBindings = new WeakHashMap<>();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	private MFXBindings() {
+	}
+
+	//================================================================================
+	// Unidirectional Bindings
+	//================================================================================
+
+	/**
+	 * Delegate for {@link Binding#create()}.
+	 */
+	public <T> Binding<T> bind() {
+		return Binding.create();
+	}
+
+	/**
+	 * Shortcut for {@code Binding.create().target(target)}.
+	 *
+	 * @see Binding
+	 */
+	public <T> Binding<T> bind(ObservableValue<? extends T> target) {
+		return Binding.<T>create().target(target);
+	}
+
+	/**
+	 * Checks if there's already a unidirectional binding for the given observable.
+	 */
+	public <T> boolean isBound(ObservableValue<? extends T> observable) {
+		return bindings.containsKey(observable);
+	}
+
+	/**
+	 * Shortcut for {@code isBound(target.getObservable())}.
+	 *
+	 * @see #isBound(ObservableValue)
+	 */
+	public <T> boolean isBound(Target<T> target) {
+		return isBound(target.getObservable());
+	}
+
+	/**
+	 * If a unidirectional binding for the given observable exists, calls {@link Binding#unbind()}.
+	 */
+	public <T> MFXBindings unbind(ObservableValue<? extends T> observable) {
+		Optional.ofNullable(bindings.get(observable))
+				.ifPresent(IBinding::unbind);
+		return this;
+	}
+
+	/**
+	 * Disposes and clears all the registered unidirectional bindings.
+	 */
+	public MFXBindings dispose() {
+		List<IBinding> bs = new ArrayList<>(bindings.values());
+		bs.forEach(IBinding::dispose);
+		return this;
+	}
+
+	/**
+	 * If a unidirectional binding exists for the given observable, calls {@link Binding#dispose()}.
+	 */
+	public <T> MFXBindings dispose(ObservableValue<? extends T> observable) {
+		Optional.ofNullable(bindings.get(observable))
+				.ifPresent(IBinding::dispose);
+		return this;
+	}
+
+	/**
+	 * @return a {@link Binding} instance for the given observable, or null
+	 * if it doesn't exist
+	 */
+	public <T> Binding<T> getBinding(ObservableValue<? extends T> observable) {
+		return bindings.get(observable);
+	}
+
+	/**
+	 * Shortcut for {@code getBinding(target.getObservable())}.
+	 *
+	 * @see #getBinding(ObservableValue)
+	 */
+	public <T> Binding<T> getBinding(Target<T> target) {
+		return getBinding(target.getObservable());
+	}
+
+	/**
+	 * Registers the given unidirectional binding in this utility.
+	 */
+	protected <T> void addBinding(Binding binding) {
+		bindings.put(binding.getTarget().getObservable(), binding);
+	}
+
+	/**
+	 * Unregisters the given unidirectional binding from this utility.
+	 */
+	protected <T> void removeBinding(Binding<T> binding) {
+		bindings.remove(binding.getTarget().getObservable());
+	}
+
+	/**
+	 * See {@link Target#isFromSource()}.
+	 */
+	public <T> boolean hasSourceChanged(ObservableValue<? extends T> observable) {
+		return Optional.ofNullable(bindings.get(observable))
+				.map(b -> b.getTarget().isFromSource())
+				.orElse(false);
+	}
+
+	/**
+	 * See {@link Target#isIgnoreBinding()}.
+	 */
+	public <T> boolean isIgnoreBinding(ObservableValue<? extends T> observable) {
+		return Optional.ofNullable(bindings.get(observable))
+				.map(b -> b.getTarget().isIgnoreBinding())
+				.orElse(false);
+	}
+
+	/**
+	 * If a {@link Binding} exists for the given observable, calls {@link Binding#invalidate()} on it.
+	 * <p>
+	 * This may be useful when creating bindings with invalidating sources with fluent API as there is no way
+	 * to refer to the binding unless it is a local variable, this helps with that.
+	 */
+	public <T> MFXBindings invTarget(ObservableValue<? extends T> observable) {
+		Optional.ofNullable(bindings.get(observable))
+				.ifPresent(Binding::invalidate);
+		return this;
+	}
+
+	//================================================================================
+	// Bidirectional Bindings
+	//================================================================================
+
+	/**
+	 * Delegate for {@link BidirectionalBinding#create()}.
+	 */
+	public <T> BidirectionalBinding<T> bindBidirectional() {
+		return BidirectionalBinding.create();
+	}
+
+	/**
+	 * Shortcut for {@code BidirectionalBinding.create().target(target)}
+	 *
+	 * @see BidirectionalBinding
+	 */
+	public <T> BidirectionalBinding<T> bindBidirectional(ObservableValue<? extends T> target) {
+		return BidirectionalBinding.<T>create().target(target);
+	}
+
+	/**
+	 * Checks if a bidirectional binding already exists for the given observable.
+	 */
+	public <T> boolean isBoundBidirectional(ObservableValue<? extends T> observable) {
+		return biBindings.containsKey(observable);
+	}
+
+	/**
+	 * Shortcut for {@code isBoundBidirectional(target.getObservable())}.
+	 *
+	 * @see #isBoundBidirectional(ObservableValue)
+	 */
+	public <T> boolean isBoundBidirectional(Target<T> target) {
+		return isBoundBidirectional(target.getObservable());
+	}
+
+	/**
+	 * If a bidirectional binding exists for the given observable, calls {@link BidirectionalBinding#unbind()}.
+	 */
+	public <T> MFXBindings unbindBidirectional(ObservableValue<? extends T> target) {
+		Optional.ofNullable(biBindings.get(target))
+				.ifPresent(IBinding::unbind);
+		return this;
+	}
+
+	/**
+	 * If a bidirectional binding exists for the given observable, calls {@link BidirectionalBinding#unbind(ObservableValue)}
+	 */
+	public <T, S> MFXBindings unbindBidirectional(ObservableValue<? extends T> target, ObservableValue<? extends S> source) {
+		Optional.ofNullable(biBindings.get(target))
+				.ifPresent(b -> b.unbind(source));
+		return this;
+	}
+
+	/**
+	 * Disposes and clears all the registered bidirectional bindings.
+	 */
+	public MFXBindings disposeBidirectionals() {
+		List<IBinding> bs = new ArrayList<>(biBindings.values());
+		bs.forEach(IBinding::dispose);
+		return this;
+	}
+
+	/**
+	 * If a bidirectional binding exists for the given observable, calls {@link BidirectionalBinding#dispose()}.
+	 */
+	public <T> MFXBindings disposeBidirectional(ObservableValue<? extends T> observable) {
+		Optional.ofNullable(biBindings.get(observable))
+				.ifPresent(IBinding::dispose);
+		return this;
+	}
+
+	/**
+	 * @return a {@link BidirectionalBinding} instance for the given observable, or null
+	 * if it doesn't exist
+	 */
+	public <T> BidirectionalBinding<T> getBiBinding(ObservableValue<? extends T> observable) {
+		return biBindings.get(observable);
+	}
+
+
+	/**
+	 * Shortcut for {@code getBiBinding(target.getObservable())}.
+	 *
+	 * @see #getBiBinding(Target)
+	 */
+	public <T> BidirectionalBinding<T> getBiBinding(Target<T> target) {
+		return getBiBinding(target.getObservable());
+	}
+
+	/**
+	 * Registers the given bidirectional binding in this utility.
+	 */
+	protected <T> void addBinding(BidirectionalBinding<T> binding) {
+		biBindings.put(binding.getTarget().getObservable(), binding);
+	}
+
+	/**
+	 * Unregisters the given bidirectional binding from this utility.
+	 */
+	protected <T> void removeBinding(BidirectionalBinding<T> binding) {
+		biBindings.remove(binding.getTarget().getObservable());
+	}
+
+	/**
+	 * If a {@link BidirectionalBinding} exists for the given observable, calls {@link BidirectionalBinding#invalidate()} on it.
+	 * <p>
+	 * This may be useful when creating bindings with invalidating sources with fluent API as there is no way
+	 * to refer to the binding unless it is a local variable, this helps with that.
+	 */
+	public <T> MFXBindings biInvalidate(ObservableValue<? extends T> observable) {
+		Optional.ofNullable(biBindings.get(observable))
+				.ifPresent(BidirectionalBinding::invalidate);
+		return this;
+	}
+
+	/**
+	 * If a {@link BidirectionalBinding} exists for the given observable, calls {@link BidirectionalBinding#invalidateSource()} on it.
+	 * <p>
+	 * This may be useful when creating bindings with invalidating sources with fluent API as there is no way
+	 * to refer to the binding unless it is a local variable, this helps with that.
+	 */
+	public <T> MFXBindings biInvalidateSources(ObservableValue<? extends T> observable) {
+		Optional.ofNullable(biBindings.get(observable))
+				.ifPresent(BidirectionalBinding::invalidateSource);
+		return this;
+	}
+
+	//================================================================================
+	// Misc
+	//================================================================================
+
+	/**
+	 * @return the number of registered unidirectional bindings
+	 */
+	public int size() {
+		return bindings.size();
+	}
+
+	/**
+	 * @return the number of registered bidirectional bindings
+	 */
+	public int biSize() {
+		return biBindings.size();
+	}
+
+	/**
+	 * @return whether {@link #size()} is 0
+	 */
+	public boolean isEmpty() {
+		return bindings.isEmpty();
+	}
+
+	/**
+	 * @return whether {@link #biSize()} is 0
+	 */
+	public boolean biIsEmpty() {
+		return biBindings.isEmpty();
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyBooleanWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public MFXBindings unbindReadOnly(ReadOnlyBooleanWrapper target, boolean bidirectional) {
+		ReadOnlyBooleanProperty obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyStringWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public MFXBindings unbindReadOnly(ReadOnlyStringWrapper target, boolean bidirectional) {
+		ReadOnlyStringProperty obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyIntegerWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public MFXBindings unbindReadOnly(ReadOnlyIntegerWrapper target, boolean bidirectional) {
+		ReadOnlyIntegerProperty obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyLongWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public MFXBindings unbindReadOnly(ReadOnlyLongWrapper target, boolean bidirectional) {
+		ReadOnlyLongProperty obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyFloatWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public MFXBindings unbindReadOnly(ReadOnlyFloatWrapper target, boolean bidirectional) {
+		ReadOnlyFloatProperty obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyDoubleWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public MFXBindings unbindReadOnly(ReadOnlyDoubleWrapper target, boolean bidirectional) {
+		ReadOnlyDoubleProperty obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+
+	/**
+	 * Retrieves the read-only property with {@link ReadOnlyObjectWrapper#getReadOnlyProperty()} and unbinds it.
+	 * <p></p>
+	 * The "bidirectional" parameter is fundamental as it determines whether {@link #unbind(ObservableValue)}
+	 * is called or {@link #unbindBidirectional(ObservableValue)}
+	 */
+	public <T> MFXBindings unbindReadOnly(ReadOnlyObjectWrapper<T> target, boolean bidirectional) {
+		ReadOnlyObjectProperty<T> obs = target.getReadOnlyProperty();
+		return bidirectional ? unbindBidirectional(obs) : unbind(obs);
+	}
+}

+ 91 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/MappedUpdater.java

@@ -0,0 +1,91 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.Updater;
+
+/**
+ * Specialization of {@link Updater} that is also capable of mapping the input before passing it to the {@link Updater}.
+ */
+public class MappedUpdater<T, M> implements Updater<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	protected Mapper<T, M> mapper;
+	protected Updater<M> updater;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected MappedUpdater() {
+	}
+
+	public MappedUpdater(Mapper<T, M> mapper, Updater<M> updater) {
+		this.mapper = mapper;
+		this.updater = updater;
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	@Override
+	public void update(T oldValue, T newValue) {
+		updater.update(
+				mapper.apply(oldValue),
+				mapper.apply(newValue)
+		);
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * @return this updater's {@link Mapper}
+	 */
+	public Mapper<T, M> getMapper() {
+		return mapper;
+	}
+
+	/**
+	 * Sets this updater's {@link Mapper}.
+	 */
+	public MappedUpdater<T, M> setMapper(Mapper<T, M> mapper) {
+		this.mapper = mapper;
+		return this;
+	}
+
+	/**
+	 * @return the {@link Updater} object
+	 */
+	public Updater<M> getUpdater() {
+		return updater;
+	}
+
+	/**
+	 * Sets the updater.
+	 */
+	public MappedUpdater<T, M> setUpdater(Updater<M> updater) {
+		this.updater = updater;
+		return this;
+	}
+
+	//================================================================================
+	// Builder
+	//================================================================================
+	public static class Builder<T, M> {
+		private final MappedUpdater<T, M> mappedUpdater = new MappedUpdater<>();
+
+		public Builder<T, M> updater(Updater<M> updater) {
+			mappedUpdater.updater = updater;
+			return this;
+		}
+
+		public Builder<T, M> mapper(Mapper<T, M> mapper) {
+			mappedUpdater.mapper = mapper;
+			return this;
+		}
+
+		public MappedUpdater<T, M> get() {
+			return mappedUpdater;
+		}
+	}
+}

+ 76 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Mapper.java

@@ -0,0 +1,76 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Specialization of {@link Function} to also add the support for "orElse".
+ *
+ * @param <T> – the type of the input to the function
+ * @param <R> – the type of the result of the function, as well as the type of the orElse supplier
+ */
+public class Mapper<T, R> implements Function<T, R> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	protected Function<T, R> fn;
+	private Supplier<R> orElse = () -> null;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected Mapper() {
+	}
+
+	public Mapper(Function<T, R> fn) {
+		this.fn = fn;
+	}
+
+	public static <T, R> Mapper<T, R> of(Function<T, R> fn) {
+		return new Mapper<>(fn);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+	@Override
+	public R apply(T t) {
+		return (t != null) ? fn.apply(t) : orElse.get();
+	}
+
+	@Override
+	public <V> Mapper<T, V> andThen(Function<? super R, ? extends V> after) {
+		return new Mapper<>(fn).andThen(after);
+	}
+
+	@Override
+	public <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
+		return new Mapper<>(fn).compose(before);
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * @return the {@link Function} of this mapper
+	 */
+	public Function<T, R> getFn() {
+		return fn;
+	}
+
+	/**
+	 * @return the "orElse" {@link Supplier} of this mapper
+	 */
+	public Supplier<R> getOrElse() {
+		return orElse;
+	}
+
+	/**
+	 * Sets the "orElse" {@link Supplier} of this mapper.
+	 */
+	public Mapper<T, R> orElse(Supplier<R> orElse) {
+		this.orElse = orElse;
+		return this;
+	}
+}

+ 220 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/MappingSource.java

@@ -0,0 +1,220 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.Updater;
+import io.github.palexdev.mfxcore.enums.BindingType;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Concrete implementation of {@link AbstractSource}. This type of {@code Source} is capable of
+ * mapping the source's type S to the target's type and vice-versa to perform both {@link #updateTarget(Object, Object)}
+ * and {@link #updateSource(Object, Object)}.
+ *
+ * @param <S> the source's observable type
+ * @param <T> the target's observable type
+ */
+public class MappingSource<S, T> extends AbstractSource<S, T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	protected MappedUpdater<S, T> targetUpdater; // From source to target
+	protected MappedUpdater<T, S> sourceUpdater; // From target to source
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected MappingSource() {
+	}
+
+	public MappingSource(ObservableValue<? extends S> observable) {
+		super(observable);
+	}
+
+	public static <S, T> MappingSource<S, T> of(ObservableValue<? extends S> observable) {
+		return new MappingSource<>(observable);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Operates differently depending on which binding activated this.
+	 * <p>
+	 * For unidirectional bindings the target instance is null so the {@link #getTargetUpdater()} is called
+	 * then exits.
+	 * <p>
+	 * For bidirectional bindings the target instance is not null. Before calling the {@link #getTargetUpdater()}
+	 * we first must check that the update is not has not been invoked because of a "bounce" effect, {@link Target#isFromSource()}.
+	 */
+	@Override
+	public void updateTarget(S oldValue, S newValue) {
+		if (target.bindingType() == BindingType.UNIDIRECTIONAL) {
+			try {
+				target.ignoreBinding = true;
+				targetUpdater.update(oldValue, newValue);
+			} finally {
+				target.ignoreBinding = false;
+			}
+			return;
+		}
+
+		if (target.isFromSource()) return;
+		targetUpdater.update(oldValue, newValue);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Operates differently depending on which binding activated this.
+	 * <p>
+	 * For unidirectional bindings the target instance is null so the {@link #getTargetUpdater()} is called
+	 * then exits.
+	 * <p>
+	 * For bidirectional bindings the target instance is not null. The call to {@link #getSourceUpdater()}
+	 * is surrounded by a try-finally block in which we also set {@link Target#isFromSource()} to true, if anything goes wrong
+	 * the finally block ensures to reset {@link Target#isFromSource()} back to false.
+	 */
+	@Override
+	public void updateSource(T oldValue, T newValue) {
+		if (target == null) {
+			sourceUpdater.update(oldValue, newValue);
+			return;
+		}
+
+		try {
+			target.fromSource = true;
+			sourceUpdater.update(oldValue, newValue);
+		} finally {
+			target.fromSource = false;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * For unidirectional bindings. The listener to this source's observable is added by using
+	 * {@link When#onChanged(ObservableValue)} and is responsible for triggering {@link #updateTarget(Object, Object)}.
+	 */
+	@Override
+	protected void listen() {
+		When.onChanged(observable)
+				.then(this::updateTarget)
+				.listen();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * For bidirectional bindings. The source's target is set to the given one.
+	 * Then {@link #listen()} is called. Then a listener to the given target is added by using
+	 * {@link When#onChanged(ObservableValue)} and is responsible for triggering {@link #updateSource(Object, Object)}.
+	 */
+	@Override
+	protected void listen(Target<T> target) {
+		listen();
+
+		this.target = target;
+		When.onChanged(target.getObservable())
+				.then(this::updateSource)
+				.listen();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Uses {@link When#disposeFor(ObservableValue)} to remove the listeners added to this source's observable
+	 * and the target's observable. Then sets all its properties to null.
+	 */
+	@Override
+	public void dispose() {
+		When.disposeFor(observable);
+		if (target != null) When.disposeFor(target.getObservable());
+		observable = null;
+		target = null;
+		targetUpdater = null;
+		sourceUpdater = null;
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * @return the {@link MappedUpdater} responsible for mapping the source's values to a compatible type and then
+	 * update the target
+	 */
+	public MappedUpdater<S, T> getTargetUpdater() {
+		return targetUpdater;
+	}
+
+	/**
+	 * Sets the {@link MappedUpdater} for the target.
+	 */
+	public MappingSource<S, T> setTargetUpdater(MappedUpdater<S, T> targetUpdater) {
+		this.targetUpdater = targetUpdater;
+		return this;
+	}
+
+	/**
+	 * Sets the {@link MappedUpdater} for the target.
+	 */
+	public MappingSource<S, T> setTargetUpdater(Mapper<S, T> mapper, Updater<T> updater) {
+		this.targetUpdater = new MappedUpdater<>(mapper, updater);
+		return this;
+	}
+
+	/**
+	 * @return the {@link MappedUpdater} responsible for mapping the target's values to a compatible type and then
+	 * update the source
+	 */
+	public MappedUpdater<T, S> getSourceUpdater() {
+		return sourceUpdater;
+	}
+
+	/**
+	 * Sets the {@link MappedUpdater} for the source.
+	 */
+	public MappingSource<S, T> setSourceUpdater(MappedUpdater<T, S> sourceUpdater) {
+		this.sourceUpdater = sourceUpdater;
+		return this;
+	}
+
+	/**
+	 * Sets the {@link MappedUpdater} for the source.
+	 */
+	public MappingSource<S, T> setSourceUpdater(Mapper<T, S> mapper, Updater<S> updater) {
+		this.sourceUpdater = new MappedUpdater<>(mapper, updater);
+		return this;
+	}
+
+	//================================================================================
+	// Builder
+	//================================================================================
+	public static class Builder<S, T> {
+		private final MappingSource<S, T> source = new MappingSource<>();
+
+		public Builder<S, T> observable(ObservableValue<? extends S> observable) {
+			source.observable = observable;
+			return this;
+		}
+
+		public Builder<S, T> targetUpdater(MappedUpdater<S, T> targetUpdater) {
+			source.targetUpdater = targetUpdater;
+			return this;
+		}
+
+		public Builder<S, T> sourceUpdater(MappedUpdater<T, S> sourceUpdater) {
+			source.sourceUpdater = sourceUpdater;
+			return this;
+		}
+
+		public MappingSource<S, T> get() {
+			if (source.observable == null) throw new NullPointerException("Source is invalid as observable is null");
+			return source;
+		}
+	}
+}
+

+ 222 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Source.java

@@ -0,0 +1,222 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.Updater;
+import io.github.palexdev.mfxcore.enums.BindingType;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Concrete implementation of {@link AbstractSource} the most basic type of source.
+ *
+ * @param <S> both the source's and target's observables type
+ */
+public class Source<S> extends AbstractSource<S, S> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	protected Updater<S> targetUpdater;
+	protected Updater<S> sourceUpdater;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	protected Source() {
+	}
+
+	public Source(ObservableValue<? extends S> observable) {
+		super(observable);
+	}
+
+	public static <S> Source<S> of(ObservableValue<? extends S> observable) {
+		return new Source<>(observable);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Operates differently depending on which binding activated this.
+	 * <p>
+	 * For unidirectional bindings the target instance is null so the {@link #getTargetUpdater()} is called
+	 * then exits.
+	 * <p>
+	 * For bidirectional bindings the target instance is not null. Before calling the {@link #getTargetUpdater()}
+	 * we first must check that the update is not has not been invoked because of a "bounce" effect, {@link Target#isFromSource()}.
+	 */
+	@Override
+	public void updateTarget(S oldValue, S newValue) {
+		if (target.bindingType() == BindingType.UNIDIRECTIONAL) {
+			try {
+				target.ignoreBinding = true;
+				targetUpdater.update(oldValue, newValue);
+			} finally {
+				target.ignoreBinding = false;
+			}
+			return;
+		}
+
+		if (target.isFromSource()) return;
+		targetUpdater.update(oldValue, newValue);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Operates differently depending on which binding activated this.
+	 * <p>
+	 * For unidirectional bindings the target instance is null so the {@link #getTargetUpdater()} is called
+	 * then exits.
+	 * <p>
+	 * For bidirectional bindings the target instance is not null. The call to {@link #getSourceUpdater()}
+	 * is surrounded by a try-finally block in which we also set {@link Target#isFromSource()} to true, if anything goes wrong
+	 * the finally block ensures to reset {@link Target#isFromSource()} back to false.
+	 */
+	@Override
+	public void updateSource(S oldValue, S newValue) {
+		if (target == null) {
+			sourceUpdater.update(oldValue, newValue);
+			return;
+		}
+
+		try {
+			target.fromSource = true;
+			sourceUpdater.update(oldValue, newValue);
+		} finally {
+			target.fromSource = false;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * For unidirectional bindings. The listener to this source's observable is added by using
+	 * {@link When#onChanged(ObservableValue)} and is responsible for triggering {@link #updateTarget(Object, Object)}.
+	 */
+	@Override
+	protected void listen() {
+		When.onChanged(observable)
+				.then(this::updateTarget)
+				.listen();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * For bidirectional bindings. The source's target is set to the given one.
+	 * Then {@link #listen()} is called. Then a listener to the given target is added by using
+	 * {@link When#onChanged(ObservableValue)} and is responsible for triggering {@link #updateSource(Object, Object)}.
+	 */
+	@Override
+	protected void listen(Target<S> target) {
+		listen();
+
+		this.target = target;
+		When.onChanged(target.getObservable())
+				.then(this::updateSource)
+				.listen();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Uses {@link When#disposeFor(ObservableValue)} to remove the listeners added to this source's observable
+	 * and the target's observable. Then sets all its properties to null.
+	 */
+	@Override
+	public void dispose() {
+		When.disposeFor(observable);
+		if (target != null) When.disposeFor(target.getObservable());
+		observable = null;
+		target = null;
+		targetUpdater = null;
+		sourceUpdater = null;
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * @return the {@link Updater} responsible for updating the target
+	 */
+	public Updater<S> getTargetUpdater() {
+		return targetUpdater;
+	}
+
+	/**
+	 * Sets the target {@link Updater}.
+	 */
+	public Source<S> setTargetUpdater(Updater<S> targetUpdater) {
+		this.targetUpdater = targetUpdater;
+		return this;
+	}
+
+	/**
+	 * @return the {@link Updater} responsible for updating the source
+	 */
+	public Updater<S> getSourceUpdater() {
+		return sourceUpdater;
+	}
+
+	/**
+	 * Sets the source {@link Updater}.
+	 */
+	public Source<S> setSourceUpdater(Updater<S> sourceUpdater) {
+		this.sourceUpdater = sourceUpdater;
+		return this;
+	}
+
+	/**
+	 * Attempts set the target updater by using {@link Updater#implicit(ObservableValue)}
+	 * on the given target.
+	 */
+	public Source<S> implicit(ObservableValue<? extends S> target) {
+		targetUpdater = Updater.implicit(target);
+		return this;
+	}
+
+	/**
+	 * Attempts to set the target and sources updater by using {@link Updater#implicit(ObservableValue)}
+	 * on both the given target and source.
+	 */
+	public Source<S> implicit(ObservableValue<? extends S> target, ObservableValue<? extends S> source) {
+		targetUpdater = Updater.implicit(target);
+		sourceUpdater = Updater.implicit(source);
+		return this;
+	}
+
+	//================================================================================
+	// Builder
+	//================================================================================
+	public static class Builder<S> {
+		private final Source<S> source = new Source<>();
+
+		public Builder<S> observable(ObservableValue<? extends S> observable) {
+			source.observable = observable;
+			return this;
+		}
+
+		public Builder<S> targetUpdater(ObservableValue<? extends S> target) {
+			source.targetUpdater = Updater.implicit(target);
+			return this;
+		}
+
+		public Builder<S> targetUpdater(Updater<S> targetUpdater) {
+			source.targetUpdater = targetUpdater;
+			return this;
+		}
+
+		public Builder<S> sourceUpdater(Updater<S> sourceUpdater) {
+			source.sourceUpdater = sourceUpdater;
+			return this;
+		}
+
+		public Source<S> get() {
+			if (source.observable == null) throw new NullPointerException("Source is invalid as observable is null");
+			return source;
+		}
+	}
+}

+ 83 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/Target.java

@@ -0,0 +1,83 @@
+package io.github.palexdev.mfxcore.base.bindings;
+
+import io.github.palexdev.mfxcore.base.bindings.base.IBinding;
+import io.github.palexdev.mfxcore.enums.BindingType;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * A simple bean to represent the target for any type of {@link IBinding}.
+ * <p>
+ * This contains the {@link ObservableValue} which will be the target of the binding (the target is the one that
+ * will be updated by the binding' sources) and other useful information that are shared across the binding instance and
+ * the sources if needed.
+ *
+ * @param <T> the observable's type
+ */
+public class Target<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private ObservableValue<? extends T> observable;
+	protected boolean fromSource;
+	protected boolean ignoreBinding;
+	protected BindingType bindingType;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public Target(ObservableValue<? extends T> observable) {
+		assert observable != null;
+		this.observable = observable;
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Disposes this target by setting tha observable to null.
+	 */
+	protected void dispose() {
+		observable = null;
+		fromSource = false;
+	}
+
+	/**
+	 * @return whether the update comes from a change of the target that is propagating to the sources
+	 */
+	public boolean isFromSource() {
+		return fromSource;
+	}
+
+	/**
+	 * @return whether the update should be done anyway, regardless the binding status
+	 */
+	public boolean isIgnoreBinding() {
+		return ignoreBinding;
+	}
+
+	/**
+	 * @return the type of binding shared between the {@link IBinding} and its sources
+	 */
+	public BindingType bindingType() {
+		return bindingType;
+	}
+
+	//================================================================================
+	// Getters/Setters
+	//================================================================================
+
+	/**
+	 * Shortcut for {@code getObservable().getValue}.
+	 */
+	public T getValue() {
+		return observable.getValue();
+	}
+
+	/**
+	 * @return the target's observable
+	 */
+	public ObservableValue<? extends T> getObservable() {
+		return observable;
+	}
+}

+ 193 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/WeakLinkedHashMap.java

@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.bindings;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * A special {@link WeakHashMap} that allows to retrieve the keys ordered by insertion.
+ * <p>
+ * Writing a {@code LinkedWeakHashMap} would have been too much work and a very hard task.
+ * For this reason this Map simply uses a {@link LinkedList} to store the keys (wrapped in {@link WeakReference}s) by
+ * their insertion order.
+ * <p></p>
+ * Just like the {@link WeakHashMap} this list is cleared (all null references are removed) when
+ * major operations occur, such as: put, putAll, combine.
+ * <p></p>
+ * Allows to retrieve the first and the last keys, and also a <b>copy</b> of the actual {@link LinkedList}.
+ */
+public class WeakLinkedHashMap<K, V> extends WeakHashMap<K, V> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private LinkedList<WeakReference<K>> orderedKeys = new LinkedList<>();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public WeakLinkedHashMap() {
+	}
+
+	public WeakLinkedHashMap(Map<? extends K, ? extends V> m) {
+		super(m);
+	}
+
+	public WeakLinkedHashMap(int initialCapacity) {
+		super(initialCapacity);
+	}
+
+	public WeakLinkedHashMap(int initialCapacity, float loadFactor) {
+		super(initialCapacity, loadFactor);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Scans the {@link LinkedList} contains the keys references and removes the null ones.
+	 * Also calls {@link #size()} to also trigger the {@link WeakHashMap} cleaning too.
+	 */
+	@SuppressWarnings("ResultOfMethodCallIgnored")
+	private void clearReferences() {
+		orderedKeys.removeIf(reference -> reference != null && reference.get() == null);
+		size();
+	}
+
+	@SafeVarargs
+	private void updateKeysList(K... keys) {
+		LinkedHashSet<K> uniqueKeys = orderedKeys.stream().map(WeakReference::get).collect(Collectors.toCollection(LinkedHashSet::new));
+		uniqueKeys.addAll(Arrays.asList(keys));
+		orderedKeys = uniqueKeys.stream().map(WeakReference::new).collect(Collectors.toCollection(LinkedList::new));
+		clearReferences();
+	}
+
+	@SafeVarargs
+	private void updateKeysList(Map.Entry<K, V>... entries) {
+		LinkedHashSet<K> uniqueKeys = orderedKeys.stream().map(WeakReference::get).collect(Collectors.toCollection(LinkedHashSet::new));
+		List<K> keys = Stream.of(entries).map(Map.Entry::getKey).collect(Collectors.toList());
+		uniqueKeys.addAll(keys);
+		orderedKeys = uniqueKeys.stream().map(WeakReference::new).collect(Collectors.toCollection(LinkedList::new));
+		clearReferences();
+	}
+
+
+	/**
+	 * Allows to combine the given {@code BindingsMap} to this one.
+	 * <p>
+	 * This method exists to ensure that insertion order is kept with the {@link LinkedList} but most
+	 * importantly ensures that there are no duplicates in the list by using a {@link LinkedHashSet}.
+	 */
+	public void combine(WeakLinkedHashMap<K, V> source) {
+		LinkedHashSet<K> uniqueKeys = Stream.concat(orderedKeys.stream(), source.orderedKeys.stream())
+				.map(WeakReference::get)
+				.collect(Collectors.toCollection(LinkedHashSet::new));
+		orderedKeys = uniqueKeys.stream().map(WeakReference::new).collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
+		clearReferences();
+		for (Map.Entry<K, V> entry : source.entrySet()) {
+			super.put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	/**
+	 * Adds the given key to the keys {@link LinkedList}, performs {@link #clearReferences()}
+	 * and then calls the super method.
+	 */
+	@Override
+	public V put(K key, V value) {
+		updateKeysList(key);
+		return super.put(key, value);
+	}
+
+	/**
+	 * Overridden to call {@link #putAll(Map.Entry[])}.
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public void putAll(Map<? extends K, ? extends V> m) {
+		putAll(m.entrySet().toArray(Map.Entry[]::new));
+	}
+
+	/**
+	 * For each entry adds the key to the keys {@link LinkedList},
+	 * then calls the super method.
+	 * At the end performs {@link #clearReferences()}.
+	 */
+	@SafeVarargs
+	public final void putAll(Map.Entry<K, V>... entries) {
+		updateKeysList(entries);
+		for (Map.Entry<K, V> entry : entries) {
+			super.put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	/**
+	 * Removes the given key from the keys {@link LinkedList}
+	 * and then calls the super method.
+	 */
+	@Override
+	public V remove(Object key) {
+		orderedKeys.removeIf(reference -> reference != null && reference.get() == key);
+		return super.remove(key);
+	}
+
+	/**
+	 * Clears the keys {@link LinkedList} and then calls the super method.
+	 */
+	@Override
+	public void clear() {
+		orderedKeys.clear();
+		super.clear();
+	}
+
+	/**
+	 * UNSUPPORTED
+	 */
+	@Override
+	public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * @return a copy of the {@link LinkedList} containing the Map's keys ordered by insertion
+	 */
+	public LinkedList<WeakReference<K>> unmodifiableKeysList() {
+		return new LinkedList<>(orderedKeys);
+	}
+
+	/**
+	 * @return the first inserted key
+	 */
+	public K getFirstKey() {
+		if (isEmpty()) return null;
+		return orderedKeys.getFirst().get();
+	}
+
+	/**
+	 * @return the last inserted key
+	 */
+	public K getLastKey() {
+		if (isEmpty()) return null;
+		return orderedKeys.getLast().get();
+	}
+}

+ 76 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/base/IBinding.java

@@ -0,0 +1,76 @@
+package io.github.palexdev.mfxcore.base.bindings.base;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Target;
+import io.github.palexdev.mfxcore.enums.BindingState;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Public APIs for both unidirectional and bidirectional bindings.
+ *
+ * @param <T> the type of the target's observable
+ */
+public interface IBinding<T> {
+
+	/**
+	 * This is the method responsible for "activating" the binding.
+	 */
+	IBinding<T> get();
+
+	/**
+	 * Invalidates the binding by forcing the source to update the target
+	 * with its current value as both old and new values.
+	 */
+	IBinding<T> invalidate();
+
+	/**
+	 * Invalidates the binding by forcing the target to update the sources
+	 * with its current value as both the old and new values.
+	 * <p></p>
+	 * Unidirectional bindings will throw an {@link UnsupportedOperationException}.
+	 */
+	IBinding<T> invalidateSource();
+
+	/**
+	 * This method is responsible for "deactivating" this binding.
+	 * <p>
+	 * Specific operations may vary according to the binding type.
+	 */
+	IBinding<T> unbind();
+
+	/**
+	 * This method is responsible for "deactivating" this binding, but unlike {@link #unbind()}
+	 * that still lets you re-set/re-use the binding, this will stop you from re-activating it.
+	 */
+	void dispose();
+
+	/**
+	 * @return the {@link Target} object responsible for keeping the binding's target
+	 * {@link ObservableValue} and other useful info.
+	 */
+	Target<T> getTarget();
+
+	/**
+	 * @return the state of the binding, see {@link BindingState}
+	 */
+	BindingState state();
+
+	/**
+	 * Checks if the state of the binding is {@link BindingState#DISPOSED}.
+	 */
+	default boolean isDisposed() {
+		return state() == BindingState.DISPOSED;
+	}
+
+	// TODO note that this checks only the state not MFXBindings
+
+	/**
+	 * Checks if the bindings state is {@link BindingState#BOUND}.
+	 * <p>
+	 * <b>Note</b> that this will only check the binding's state and not the target.
+	 * A full check should also consider calling {@link MFXBindings#isBound(Target)}.
+	 */
+	default boolean mayBeBound() {
+		return state() == BindingState.BOUND;
+	}
+}

+ 42 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/base/ISource.java

@@ -0,0 +1,42 @@
+package io.github.palexdev.mfxcore.base.bindings.base;
+
+import io.github.palexdev.mfxcore.base.bindings.MappingSource;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Public API every type of {@code Source} must implement.
+ * <p>
+ * The interface has two generics as it makes it easier to implement {@link MappingSource}s.
+ *
+ * @param <S> the type of the source's observable
+ * @param <T> the type of the target's observable
+ */
+public interface ISource<S, T> {
+
+	/**
+	 * @return the source's {@link ObservableValue}
+	 */
+	ObservableValue<? extends S> getObservable();
+
+	/**
+	 * Uses the values of the source's observable to update the target.
+	 */
+	void updateTarget(S oldValue, S newValue);
+
+	/**
+	 * Uses the values of the target's observable to update the sources.
+	 */
+	void updateSource(T oldValue, T newValue);
+
+	/**
+	 * Disposes the source.
+	 */
+	void dispose();
+
+	/**
+	 * Shortcut for {@code getObservable().getValue()}.
+	 */
+	default S getValue() {
+		return getObservable().getValue();
+	}
+}

+ 69 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/bindings/base/Updater.java

@@ -0,0 +1,69 @@
+package io.github.palexdev.mfxcore.base.bindings.base;
+
+import io.github.palexdev.mfxcore.base.bindings.Target;
+import javafx.beans.property.Property;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+
+import java.util.Objects;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Can be considered as a mix of {@link Consumer} and {@link BiConsumer}. Has only one generic type
+ * but the method expects two values of the same type. This is specifically made for use with
+ * binding' sources and {@link ChangeListener}s.
+ *
+ * @param <T> the type of the input to the operation
+ */
+@FunctionalInterface
+public interface Updater<T> {
+
+	/**
+	 * Performs this operation on the given oldValue and newValue.
+	 */
+	void update(T oldValue, T newValue);
+
+	/**
+	 * Returns a composed {@code Updater} that performs, in sequence, this
+	 * operation followed by the {@code after} operation. If performing either
+	 * operation throws an exception, it is relayed to the caller of the
+	 * composed operation. If performing this operation throws an exception,
+	 * the {@code after} operation will not be performed.
+	 *
+	 * @param after the operation to perform after this operation
+	 * @return a composed {@code Updater} that performs in sequence this
+	 * operation followed by the {@code after} operation
+	 * @throws NullPointerException if {@code after} is null
+	 */
+	default Updater<T> andThen(Updater<? super T> after) {
+		Objects.requireNonNull(after);
+		return (oldValue, newValue) -> {
+			update(oldValue, newValue);
+			after.update(oldValue, newValue);
+		};
+	}
+
+	/**
+	 * Attempts to create an {@code Updater} for the given {@link ObservableValue}.
+	 * This works only for observables that are instance of {@link Property}, as the most
+	 * basic {@code Updater} for them is {@code (oldValue, newValue) -> property.setValue(newValue)}.
+	 *
+	 * @throws IllegalArgumentException if the given {@link ObservableValue} is not instance of {@link Property}
+	 */
+	@SuppressWarnings({"rawtypes", "unchecked"})
+	static <T> Updater<T> implicit(ObservableValue observable) {
+		if (!(observable instanceof Property)) {
+			throw new IllegalArgumentException("Cannot create implicit updater for " + observable);
+		}
+		return (oldValue, newValue) -> ((Property<T>) observable).setValue(newValue);
+	}
+
+	/**
+	 * Calls {@link #implicit(ObservableValue)} with {@link Target#getObservable()}.
+	 */
+	@SuppressWarnings("rawtypes")
+	static <T> Updater<T> implicit(Target target) {
+		return implicit(target.getObservable());
+	}
+}

+ 45 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/CharProperty.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties;
+
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+/**
+ * Simple extension of {@link ReadOnlyObjectWrapper} for {@link Character}s.
+ */
+public class CharProperty extends ReadOnlyObjectWrapper<Character> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public CharProperty() {
+	}
+
+	public CharProperty(Character initialValue) {
+		super(initialValue);
+	}
+
+	public CharProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public CharProperty(Object bean, String name, Character initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 50 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/EventHandlerProperty.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps an {@link EventHandler} for an {@link Event} of type T.
+ *
+ * @param <T> the type of {@link Event}
+ */
+public class EventHandlerProperty<T extends Event> extends ReadOnlyObjectWrapper<EventHandler<T>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public EventHandlerProperty() {
+	}
+
+	public EventHandlerProperty(EventHandler<T> initialValue) {
+		super(initialValue);
+	}
+
+	public EventHandlerProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public EventHandlerProperty(Object bean, String name, EventHandler<T> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 120 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/PositionProperty.java

@@ -0,0 +1,120 @@
+package io.github.palexdev.mfxcore.base.properties;
+
+import io.github.palexdev.mfxcore.base.beans.Position;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.Optional;
+
+/**
+ * Simple extension of {@link ReadOnlyObjectWrapper} for {@link Position} objects.
+ */
+public class PositionProperty extends ReadOnlyObjectWrapper<Position> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public PositionProperty() {
+	}
+
+	public PositionProperty(Position initialValue) {
+		super(initialValue);
+	}
+
+	public PositionProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public PositionProperty(Object bean, String name, Position initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Convenience method to create a new {@link Position} object with the given parameters and set it
+	 * as the new value of this property.
+	 */
+	public void setPosition(double x, double y) {
+		set(Position.of(x, y));
+	}
+
+	/**
+	 * Convenience method to set only the x of the current {@link Position} of this property.
+	 * Note that if the value is null a new {@link Position} object is created with Y = 0.0.
+	 * Also, if the value was not null, {@link #invalidated()} and {@link #fireValueChangedEvent()} are invoked programmatically
+	 * only if the x was not the same as the given one, this is needed as the object will remain the same.
+	 */
+	public void setX(double x) {
+		Optional.ofNullable(get())
+				.ifPresentOrElse(
+						p -> {
+							boolean changed = p.getX() != x;
+							p.setX(x);
+							if (changed) {
+								invalidated();
+								fireValueChangedEvent();
+							}
+						},
+						() -> setPosition(x, 0)
+				);
+	}
+
+	/**
+	 * Convenience method to set only the y of the current {@link Position} of this property.
+	 * Note that if the value is null a new {@link Position} object is created with  X = 0.0.
+	 * Also, if the value was not null, {@link #invalidated()} and {@link #fireValueChangedEvent()} are invoked programmatically
+	 * only if the y was not the same as the given one, this is needed as the object will remain the same.
+	 */
+	public void setY(double y) {
+		Optional.ofNullable(get())
+				.ifPresentOrElse(
+						p -> {
+							boolean changed = p.getY() != y;
+							p.setY(y);
+							if (changed) {
+								invalidated();
+								fireValueChangedEvent();
+							}
+						},
+						() -> setPosition(0, y)
+				);
+	}
+
+	/**
+	 * Null-safe alternative to {@code get().getX()}, if the value is null returns 0.0.
+	 */
+	public double getX() {
+		return Optional.ofNullable(get())
+				.map(Position::getX)
+				.orElse(0.0);
+	}
+
+	/**
+	 * Null-safe alternative to {@code get().getX()}, if the value is null returns the given value.
+	 */
+	public double getX(double or) {
+		return Optional.ofNullable(get())
+				.map(Position::getX)
+				.orElse(or);
+	}
+
+	/**
+	 * Null-safe alternative to {@code get().getY()}, if the value is null returns 0.0.
+	 */
+	public double getY() {
+		return Optional.ofNullable(get())
+				.map(Position::getY)
+				.orElse(0.0);
+	}
+
+	/**
+	 * Null-safe alternative to {@code get().getY()}, if the value is null returns the given value.
+	 */
+	public double getY(double or) {
+		return Optional.ofNullable(get())
+				.map(Position::getY)
+				.orElse(or);
+	}
+}

+ 102 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/SizeProperty.java

@@ -0,0 +1,102 @@
+package io.github.palexdev.mfxcore.base.properties;
+
+import io.github.palexdev.mfxcore.base.beans.Size;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.Optional;
+
+/**
+ * Simple extension of {@link ReadOnlyObjectWrapper} for {@link Size} objects.
+ */
+public class SizeProperty extends ReadOnlyObjectWrapper<Size> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SizeProperty() {
+	}
+
+	public SizeProperty(Size initialValue) {
+		super(initialValue);
+	}
+
+	public SizeProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public SizeProperty(Object bean, String name, Size initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Convenience method to create a new {@link Size} object with the given parameters and set it
+	 * as the new value of this property.
+	 */
+	public void setSize(double w, double h) {
+		set(Size.of(w, h));
+	}
+
+	/**
+	 * Convenience method to set only the width of the current {@link Size} of this property.
+	 * Note that if the value is null a new {@link Size} object is created with a height of 0.0.
+	 * Also, if the value was not null, {@link #invalidated()} and {@link #fireValueChangedEvent()} are invoked programmatically
+	 * only if the width was not the same as the given one, this is needed as the object will remain the same.
+	 */
+	public void setWidth(double w) {
+		Optional.ofNullable(get())
+				.ifPresentOrElse(
+						s -> {
+							boolean changed = s.getWidth() != w;
+							s.setWidth(w);
+							if (changed) {
+								invalidated();
+								fireValueChangedEvent();
+							}
+						},
+						() -> setSize(w, 0.0)
+				);
+	}
+
+	/**
+	 * Convenience method to set only the height of the current {@link Size} of this property.
+	 * Note that if the value is null a new {@link Size} object is created with a width of 0.0.
+	 * Also, if the value was not null, {@link #invalidated()}, {@link #fireValueChangedEvent()} are invoked programmatically
+	 * only if the height was not the same as the given one, this is needed as the object will remain the same.
+	 */
+	public void setHeight(double h) {
+		Optional.ofNullable(get())
+				.ifPresentOrElse(
+						s -> {
+							boolean changed = s.getHeight() != h;
+							s.setHeight(h);
+							if (changed) {
+								invalidated();
+								fireValueChangedEvent();
+							}
+						},
+						() -> setSize(0.0, h)
+				);
+	}
+
+	/**
+	 * Null-safe alternative to {@code get().getWidth()}, if the value is null returns an invalid width of -1.0.
+	 */
+	public double getWidth() {
+		return Optional.ofNullable(get())
+				.map(Size::getWidth)
+				.orElse(-1.0);
+	}
+
+	/**
+	 * Null-safe alternative to {@code get().getHeight()}, if the value is null returns an invalid height of -1.0.
+	 */
+	public double getHeight() {
+		return Optional.ofNullable(get())
+				.map(Size::getHeight)
+				.orElse(-1.0);
+	}
+}

+ 97 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/base/NumberRangeProperty.java

@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.base;
+
+import io.github.palexdev.mfxcore.base.beans.range.NumberRange;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link NumberRange}.
+ *
+ * @param <N> the range's number type
+ */
+public abstract class NumberRangeProperty<N extends Number & Comparable<N>> extends ReadOnlyObjectWrapper<NumberRange<N>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public NumberRangeProperty() {
+	}
+
+	public NumberRangeProperty(NumberRange<N> initialValue) {
+		super(initialValue);
+	}
+
+	public NumberRangeProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public NumberRangeProperty(Object bean, String name, NumberRange<N> initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Abstract Methods
+	//================================================================================
+
+	/**
+	 * Convenience method to set a range with both min and max equal.
+	 */
+	public abstract void setRange(N value);
+
+	/**
+	 * Convenience method to set a range with the given min and max values.
+	 */
+	public abstract void setRange(N min, N max);
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Convenience method to get the range's lower bound.
+	 * Null if the range is null.
+	 */
+	public N getMin() {
+		return get() == null ? null : get().getMin();
+	}
+
+	/**
+	 * Convenience method to get the range's upper bound.
+	 * Null if the range is null.
+	 */
+	public N getMax() {
+		return get() == null ? null : get().getMin();
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+
+	/**
+	 * Overridden to check equality between ranges and return in case ranges are the same.
+	 */
+	@Override
+	public void set(NumberRange<N> newValue) {
+		NumberRange<N> oldValue = get();
+		if (newValue.equals(oldValue)) return;
+		super.set(newValue);
+	}
+}

+ 58 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/base/ResettableProperty.java

@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.base;
+
+import javafx.beans.property.Property;
+
+/**
+ * Base interface for all resettable properties.
+ *
+ * @param <T> the type of the wrapped value
+ */
+public interface ResettableProperty<T> extends Property<T> {
+
+	/**
+	 * Sets the property's value to the default value.
+	 */
+	default void reset() {
+		setValue(getDefaultValue());
+	}
+
+	boolean isFireChangeOnReset();
+
+	/**
+	 * Specifies if the property should fire a change event when it is reset or not.
+	 */
+	void setFireChangeOnReset(boolean fireChangeOnReset);
+
+	/**
+	 * @return true if the property has been reset.
+	 */
+	boolean hasBeenReset();
+
+	/**
+	 * @return the property's default value
+	 */
+	T getDefaultValue();
+
+	/**
+	 * Sets the property's default value to the given value.
+	 */
+	void setDefaultValue(T defaultValue);
+}

+ 98 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/base/SynchronizedProperty.java

@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.base;
+
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.value.ObservableValue;
+
+public interface SynchronizedProperty<T> extends Property<T> {
+
+	/**
+	 * Sets this property's state to "waiting" then uses {@link When#onChanged(ObservableValue)}
+	 * to "awake" the property when the given observable changes.
+	 * <p></p>
+	 * Just like JavaFX properties if the new value is the same as the current value the method returns and does nothing.
+	 *
+	 * @param value      the new value of the property
+	 * @param observable the observable to wait for
+	 * @throws IllegalArgumentException if the given observable is the property itself or if the passed observable
+	 *                                  is another SynchronizedProperty, and it is already waiting for some other observable
+	 * @throws IllegalStateException    if this property is already waiting for another observable
+	 */
+	void setAndWait(T value, ObservableValue<?> observable);
+
+	/**
+	 * @return whether this property is in waiting state
+	 */
+	boolean isWaiting();
+
+	/**
+	 * @return the waiting state property as a read only property
+	 */
+	ReadOnlyBooleanProperty waiting();
+
+	/**
+	 * Awakes the property by setting {@link #waiting()} to false.
+	 * <p></p>
+	 * This method should never be invoked by the user, the awakening is automatically
+	 * managed by the property. If for some reason the property stays in waiting state you
+	 * are probably doing something wrong.
+	 */
+	void awake();
+
+	/**
+	 * Helper class to avoid code duplication.
+	 */
+	class Helper {
+
+		/**
+		 * Check some parameters before proceeding with the set and wait method
+		 *
+		 * @param value      the new value of the property
+		 * @param observable the observable to wait for
+		 * @return whether the check failed
+		 * @throws IllegalArgumentException if the given observable is the property itself or if the passed observable
+		 *                                  is another SynchronizedProperty, and it is already waiting for some other observable
+		 * @throws IllegalStateException    if the property is bound unidirectionally, or
+		 *                                  if this property is already waiting for another observable
+		 */
+		public static <T> boolean check(SynchronizedProperty<T> property, T value, ObservableValue<?> observable) {
+			if (observable == property) {
+				throw new IllegalArgumentException("The passed property cannot be the same as this!" +
+						" Proceeding with this method would lead to a deadlock.");
+			}
+			if (property.isBound()) {
+				throw new IllegalStateException("A bound value cannot be set!");
+			}
+			if (property.isWaiting()) {
+				throw new IllegalStateException("The property is already waiting for some other observable!");
+			}
+			if (observable instanceof SynchronizedProperty) {
+				SynchronizedProperty<?> synchronizedProperty = (SynchronizedProperty<?>) observable;
+				if (synchronizedProperty.isWaiting()) {
+					throw new IllegalArgumentException("The passed property is already waiting for some other property!" +
+							" Proceeding with this method would lead to a deadlock.");
+				}
+			}
+			return property.getValue() == null || !property.getValue().equals(value);
+		}
+	}
+}

+ 51 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/BiConsumerProperty.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.BiConsumer;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link BiConsumer}.
+ *
+ * @param <T> the consumer's first argument
+ * @param <U> the consumer's second argument
+ */
+public class BiConsumerProperty<T, U> extends ReadOnlyObjectWrapper<BiConsumer<T, U>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public BiConsumerProperty() {
+	}
+
+	public BiConsumerProperty(BiConsumer<T, U> initialValue) {
+		super(initialValue);
+	}
+
+	public BiConsumerProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public BiConsumerProperty(Object bean, String name, BiConsumer<T, U> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 52 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/BiFunctionProperty.java

@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.BiFunction;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link BiFunction}.
+ *
+ * @param <T> the function's first argument
+ * @param <U> the function's second argument
+ * @param <R> the function's return type
+ */
+public class BiFunctionProperty<T, U, R> extends ReadOnlyObjectWrapper<BiFunction<T, U, R>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public BiFunctionProperty() {
+	}
+
+	public BiFunctionProperty(BiFunction<T, U, R> initialValue) {
+		super(initialValue);
+	}
+
+	public BiFunctionProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public BiFunctionProperty(Object bean, String name, BiFunction<T, U, R> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 51 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/BiPredicateProperty.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.BiPredicate;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link BiPredicate}.
+ *
+ * @param <T> the predicate's first argument
+ * @param <U> the predicate's second argument
+ */
+public class BiPredicateProperty<T, U> extends ReadOnlyObjectWrapper<BiPredicate<T, U>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public BiPredicateProperty() {
+	}
+
+	public BiPredicateProperty(BiPredicate<T, U> initialValue) {
+		super(initialValue);
+	}
+
+	public BiPredicateProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public BiPredicateProperty(Object bean, String name, BiPredicate<T, U> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 50 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/ComparatorProperty.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.Comparator;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link Comparator}.
+ *
+ * @param <T> the type of objects that may be compared by the comparator
+ */
+public class ComparatorProperty<T> extends ReadOnlyObjectWrapper<Comparator<T>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ComparatorProperty() {
+	}
+
+	public ComparatorProperty(Comparator<T> initialValue) {
+		super(initialValue);
+	}
+
+	public ComparatorProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ComparatorProperty(Object bean, String name, Comparator<T> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 50 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/ConsumerProperty.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.Consumer;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link Consumer}.
+ *
+ * @param <T> the consumer's input type
+ */
+public class ConsumerProperty<T> extends ReadOnlyObjectWrapper<Consumer<T>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ConsumerProperty() {
+	}
+
+	public ConsumerProperty(Consumer<T> initialValue) {
+		super(initialValue);
+	}
+
+	public ConsumerProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ConsumerProperty(Object bean, String name, Consumer<T> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 51 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/FunctionProperty.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.Function;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link Function}.
+ *
+ * @param <T> the function's input type
+ * @param <R> the function's return type
+ */
+public class FunctionProperty<T, R> extends ReadOnlyObjectWrapper<Function<T, R>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public FunctionProperty() {
+	}
+
+	public FunctionProperty(Function<T, R> initialValue) {
+		super(initialValue);
+	}
+
+	public FunctionProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public FunctionProperty(Object bean, String name, Function<T, R> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 50 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/PredicateProperty.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.Predicate;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link Predicate}.
+ *
+ * @param <T> the predicate's input type
+ */
+public class PredicateProperty<T> extends ReadOnlyObjectWrapper<Predicate<T>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public PredicateProperty() {
+	}
+
+	public PredicateProperty(Predicate<T> initialValue) {
+		super(initialValue);
+	}
+
+	public PredicateProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public PredicateProperty(Object bean, String name, Predicate<T> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 50 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/SupplierProperty.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+import java.util.function.Supplier;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link Supplier}.
+ *
+ * @param <T> the supplier's return type
+ */
+public class SupplierProperty<T> extends ReadOnlyObjectWrapper<Supplier<T>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SupplierProperty() {
+	}
+
+	public SupplierProperty(Supplier<T> initialValue) {
+		super(initialValue);
+	}
+
+	public SupplierProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public SupplierProperty(Object bean, String name, Supplier<T> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 51 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/TriConsumerProperty.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import io.github.palexdev.mfxcore.base.TriConsumer;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link TriConsumer}.
+ *
+ * @param <T> the consumer's first argument
+ * @param <U> the consumer's second argument
+ * @param <R> the consumer's third argument
+ */
+public class TriConsumerProperty<T, U, R> extends ReadOnlyObjectWrapper<TriConsumer<T, U, R>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public TriConsumerProperty() {
+	}
+
+	public TriConsumerProperty(TriConsumer<T, U, R> initialValue) {
+		super(initialValue);
+	}
+
+	public TriConsumerProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public TriConsumerProperty(Object bean, String name, TriConsumer<T, U, R> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 52 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/functional/TriFunctionProperty.java

@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.functional;
+
+import io.github.palexdev.mfxcore.base.TriFunction;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+
+/**
+ * Simply an {@link ObjectProperty} that wraps a {@link TriFunction}.
+ *
+ * @param <T> the function's first argument
+ * @param <U> the function's second argument
+ * @param <V> the function's third argument
+ * @param <R> the function's return type
+ */
+public class TriFunctionProperty<T, U, V, R> extends ReadOnlyObjectWrapper<TriFunction<T, U, V, R>> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public TriFunctionProperty() {
+	}
+
+	public TriFunctionProperty(TriFunction<T, U, V, R> initialValue) {
+		super(initialValue);
+	}
+
+	public TriFunctionProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public TriFunctionProperty(Object bean, String name, TriFunction<T, U, V, R> initialValue) {
+		super(bean, name, initialValue);
+	}
+}

+ 60 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/DoubleRangeProperty.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.range;
+
+import io.github.palexdev.mfxcore.base.beans.range.DoubleRange;
+import io.github.palexdev.mfxcore.base.beans.range.NumberRange;
+import io.github.palexdev.mfxcore.base.properties.base.NumberRangeProperty;
+
+/**
+ * Implementation of {@link NumberRangeProperty} for {@code Double} ranges.
+ */
+public class DoubleRangeProperty extends NumberRangeProperty<Double> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public DoubleRangeProperty() {
+	}
+
+	public DoubleRangeProperty(NumberRange<Double> initialValue) {
+		super(initialValue);
+	}
+
+	public DoubleRangeProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public DoubleRangeProperty(Object bean, String name, NumberRange<Double> initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public void setRange(Double value) {
+		set(DoubleRange.of(value));
+	}
+
+	@Override
+	public void setRange(Double min, Double max) {
+		set(DoubleRange.of(min, max));
+	}
+}

+ 60 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/FloatRangeProperty.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.range;
+
+import io.github.palexdev.mfxcore.base.beans.range.FloatRange;
+import io.github.palexdev.mfxcore.base.beans.range.NumberRange;
+import io.github.palexdev.mfxcore.base.properties.base.NumberRangeProperty;
+
+/**
+ * Implementation of {@link NumberRangeProperty} for {@code Float} ranges.
+ */
+public class FloatRangeProperty extends NumberRangeProperty<Float> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public FloatRangeProperty() {
+	}
+
+	public FloatRangeProperty(NumberRange<Float> initialValue) {
+		super(initialValue);
+	}
+
+	public FloatRangeProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public FloatRangeProperty(Object bean, String name, NumberRange<Float> initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public void setRange(Float value) {
+		set(FloatRange.of(value));
+	}
+
+	@Override
+	public void setRange(Float min, Float max) {
+		set(FloatRange.of(min, max));
+	}
+}

+ 60 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/IntegerRangeProperty.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.range;
+
+import io.github.palexdev.mfxcore.base.beans.range.IntegerRange;
+import io.github.palexdev.mfxcore.base.beans.range.NumberRange;
+import io.github.palexdev.mfxcore.base.properties.base.NumberRangeProperty;
+
+/**
+ * Implementation of {@link NumberRangeProperty} for {@code Integer} ranges.
+ */
+public class IntegerRangeProperty extends NumberRangeProperty<Integer> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public IntegerRangeProperty() {
+	}
+
+	public IntegerRangeProperty(NumberRange<Integer> initialValue) {
+		super(initialValue);
+	}
+
+	public IntegerRangeProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public IntegerRangeProperty(Object bean, String name, NumberRange<Integer> initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public void setRange(Integer value) {
+		set(IntegerRange.of(value));
+	}
+
+	@Override
+	public void setRange(Integer min, Integer max) {
+		set(IntegerRange.of(min, max));
+	}
+}

+ 60 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/range/LongRangeProperty.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.range;
+
+import io.github.palexdev.mfxcore.base.beans.range.LongRange;
+import io.github.palexdev.mfxcore.base.beans.range.NumberRange;
+import io.github.palexdev.mfxcore.base.properties.base.NumberRangeProperty;
+
+/**
+ * Implementation of {@link NumberRangeProperty} for {@code Long} ranges.
+ */
+public class LongRangeProperty extends NumberRangeProperty<Long> {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public LongRangeProperty() {
+	}
+
+	public LongRangeProperty(NumberRange<Long> initialValue) {
+		super(initialValue);
+	}
+
+	public LongRangeProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public LongRangeProperty(Object bean, String name, NumberRange<Long> initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	//================================================================================
+	// Overridden Methods
+	//================================================================================
+	@Override
+	public void setRange(Long value) {
+		set(LongRange.of(value));
+	}
+
+	@Override
+	public void setRange(Long min, Long max) {
+		set(LongRange.of(min, max));
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableBooleanProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.SimpleBooleanProperty;
+
+/**
+ * A {@link SimpleBooleanProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableBooleanProperty extends ReadOnlyBooleanWrapper implements ResettableProperty<Boolean> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private boolean defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableBooleanProperty() {
+	}
+
+	public ResettableBooleanProperty(boolean initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableBooleanProperty(boolean initialValue, boolean defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableBooleanProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableBooleanProperty(Object bean, String name, boolean initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableBooleanProperty(Object bean, String name, boolean initialValue, boolean defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(boolean newValue) {
+		hasBeenReset = newValue == defaultValue;
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue() == defaultValue && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public Boolean getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(Boolean defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableDoubleProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyDoubleWrapper;
+import javafx.beans.property.SimpleDoubleProperty;
+
+/**
+ * A {@link SimpleDoubleProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableDoubleProperty extends ReadOnlyDoubleWrapper implements ResettableProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private double defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableDoubleProperty() {
+	}
+
+	public ResettableDoubleProperty(double initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableDoubleProperty(double initialValue, double defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableDoubleProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableDoubleProperty(Object bean, String name, double initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableDoubleProperty(Object bean, String name, double initialValue, Double defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(double newValue) {
+		hasBeenReset = newValue == defaultValue;
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue() == defaultValue && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public Double getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(Number defaultValue) {
+		this.defaultValue = defaultValue.doubleValue();
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableFloatProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyFloatWrapper;
+import javafx.beans.property.SimpleFloatProperty;
+
+/**
+ * A {@link SimpleFloatProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableFloatProperty extends ReadOnlyFloatWrapper implements ResettableProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private float defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableFloatProperty() {
+	}
+
+	public ResettableFloatProperty(float initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableFloatProperty(float initialValue, float defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableFloatProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableFloatProperty(Object bean, String name, float initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableFloatProperty(Object bean, String name, float initialValue, Float defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(float newValue) {
+		hasBeenReset = newValue == defaultValue;
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue() == defaultValue && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public Float getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(Number defaultValue) {
+		this.defaultValue = defaultValue.floatValue();
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableIntegerProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyIntegerWrapper;
+import javafx.beans.property.SimpleIntegerProperty;
+
+/**
+ * A {@link SimpleIntegerProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableIntegerProperty extends ReadOnlyIntegerWrapper implements ResettableProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private int defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableIntegerProperty() {
+	}
+
+	public ResettableIntegerProperty(int initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableIntegerProperty(int initialValue, int defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableIntegerProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableIntegerProperty(Object bean, String name, int initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableIntegerProperty(Object bean, String name, int initialValue, int defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(int newValue) {
+		hasBeenReset = newValue == defaultValue;
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue() == defaultValue && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public Integer getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(Number defaultValue) {
+		this.defaultValue = defaultValue.intValue();
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableLongProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyLongWrapper;
+import javafx.beans.property.SimpleLongProperty;
+
+/**
+ * A {@link SimpleLongProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableLongProperty extends ReadOnlyLongWrapper implements ResettableProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private long defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableLongProperty() {
+	}
+
+	public ResettableLongProperty(long initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableLongProperty(long initialValue, long defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableLongProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableLongProperty(Object bean, String name, long initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableLongProperty(Object bean, String name, long initialValue, long defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(long newValue) {
+		hasBeenReset = newValue == defaultValue;
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue() == defaultValue && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public Long getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(Number defaultValue) {
+		this.defaultValue = defaultValue.longValue();
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableObjectProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.beans.property.SimpleObjectProperty;
+
+/**
+ * A {@link SimpleObjectProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableObjectProperty<T> extends ReadOnlyObjectWrapper<T> implements ResettableProperty<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private T defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableObjectProperty() {
+	}
+
+	public ResettableObjectProperty(T initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableObjectProperty(T initialValue, T defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableObjectProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableObjectProperty(Object bean, String name, T initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableObjectProperty(Object bean, String name, T initialValue, T defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(T newValue) {
+		hasBeenReset = newValue == defaultValue;
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue().equals(defaultValue) && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public T getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(T defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+}

+ 106 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/resettable/ResettableStringProperty.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.resettable;
+
+import io.github.palexdev.mfxcore.base.properties.base.ResettableProperty;
+import javafx.beans.property.ReadOnlyStringWrapper;
+import javafx.beans.property.SimpleStringProperty;
+
+/**
+ * A {@link SimpleStringProperty} that implements {@link ResettableProperty}.
+ */
+public class ResettableStringProperty extends ReadOnlyStringWrapper implements ResettableProperty<String> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private String defaultValue;
+	private boolean fireChangeOnReset = false;
+	private boolean hasBeenReset = false;
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public ResettableStringProperty() {
+	}
+
+	public ResettableStringProperty(String initialValue) {
+		super(initialValue);
+	}
+
+	public ResettableStringProperty(String initialValue, String defaultValue) {
+		super(initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	public ResettableStringProperty(Object bean, String name) {
+		super(bean, name);
+	}
+
+	public ResettableStringProperty(Object bean, String name, String initialValue) {
+		super(bean, name, initialValue);
+	}
+
+	public ResettableStringProperty(Object bean, String name, String initialValue, String defaultValue) {
+		super(bean, name, initialValue);
+		this.defaultValue = defaultValue;
+	}
+
+	//================================================================================
+	// Override Methods
+	//================================================================================
+	@Override
+	public boolean isFireChangeOnReset() {
+		return fireChangeOnReset;
+	}
+
+	@Override
+	public void setFireChangeOnReset(boolean fireChangeOnReset) {
+		this.fireChangeOnReset = fireChangeOnReset;
+	}
+
+	@Override
+	public void set(String newValue) {
+		hasBeenReset = newValue.equals(defaultValue);
+		super.set(newValue);
+	}
+
+	@Override
+	protected void fireValueChangedEvent() {
+		if (getValue().equals(defaultValue) && !fireChangeOnReset) {
+			return;
+		}
+
+		super.fireValueChangedEvent();
+	}
+
+	@Override
+	public boolean hasBeenReset() {
+		return hasBeenReset;
+	}
+
+	@Override
+	public String getDefaultValue() {
+		return defaultValue;
+	}
+
+	@Override
+	public void setDefaultValue(String defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableBooleanProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableBooleanProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableBooleanProperty extends SimpleStyleableBooleanProperty {
+
+	public StyleableBooleanProperty(CssMetaData<? extends Styleable, Boolean> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableBooleanProperty(CssMetaData<? extends Styleable, Boolean> cssMetaData, boolean initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableBooleanProperty(CssMetaData<? extends Styleable, Boolean> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableBooleanProperty(CssMetaData<? extends Styleable, Boolean> cssMetaData, Object bean, String name, boolean initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableDoubleProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableDoubleProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableDoubleProperty extends SimpleStyleableDoubleProperty {
+
+	public StyleableDoubleProperty(CssMetaData<? extends Styleable, Number> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableDoubleProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Double initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableDoubleProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableDoubleProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name, Double initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableFloatProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableFloatProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableFloatProperty extends SimpleStyleableFloatProperty {
+
+	public StyleableFloatProperty(CssMetaData<? extends Styleable, Number> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableFloatProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Float initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableFloatProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableFloatProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name, Float initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableIntegerProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableIntegerProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableIntegerProperty extends SimpleStyleableIntegerProperty {
+
+	public StyleableIntegerProperty(CssMetaData<? extends Styleable, Number> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableIntegerProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Integer initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableIntegerProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableIntegerProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name, Integer initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableLongProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableLongProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableLongProperty extends SimpleStyleableLongProperty {
+
+	public StyleableLongProperty(CssMetaData<? extends Styleable, Number> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableLongProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Long initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableLongProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableLongProperty(CssMetaData<? extends Styleable, Number> cssMetaData, Object bean, String name, Long initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableObjectProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableObjectProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableObjectProperty<T> extends SimpleStyleableObjectProperty<T> {
+
+	public StyleableObjectProperty(CssMetaData<? extends Styleable, T> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableObjectProperty(CssMetaData<? extends Styleable, T> cssMetaData, T initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableObjectProperty(CssMetaData<? extends Styleable, T> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableObjectProperty(CssMetaData<? extends Styleable, T> cssMetaData, Object bean, String name, T initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 96 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableSizeProperty.java

@@ -0,0 +1,96 @@
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import io.github.palexdev.mfxcore.base.beans.Size;
+import javafx.css.*;
+import javafx.scene.text.Font;
+
+import java.util.Arrays;
+
+/**
+ * Convenience {@link StyleableObjectProperty} for {@link Size}, settable via CSS thanks to
+ * {@link SizeConverter}.
+ */
+public class StyleableSizeProperty extends StyleableObjectProperty<Size> {
+	public StyleableSizeProperty(CssMetaData<? extends Styleable, Size> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableSizeProperty(CssMetaData<? extends Styleable, Size> cssMetaData, Size initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableSizeProperty(CssMetaData<? extends Styleable, Size> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableSizeProperty(CssMetaData<? extends Styleable, Size> cssMetaData, Object bean, String name, Size initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	public void setSize(double width, double height) {
+		set(Size.of(width, height));
+	}
+
+	@Override
+	public void applyStyle(StyleOrigin origin, Size v) {
+		if (v == null) return;
+		super.applyStyle(origin, v);
+	}
+
+	//================================================================================
+	// Internal Classes
+	//================================================================================
+
+	/**
+	 * Style converter implementation to make {@link Size} settable via CSS.
+	 * The related property is {@link StyleableSizeProperty}.
+	 * <p>
+	 * For this to properly work, you must use a specific format. The converter expects a string value,
+	 * with two double numbers which will be in order the width and the height for the new {@code Size}, so:
+	 * <pre>
+	 * {@code
+	 * .node {
+	 *     -fx-property-name: "100 30";
+	 * }
+	 * }
+	 * </pre>
+	 */
+	public static class SizeConverter extends StyleConverter<String, Size> {
+
+		// lazy, thread-safe instantiation
+		private static class Holder {
+			static final SizeConverter INSTANCE = new SizeConverter();
+		}
+
+		/**
+		 * Gets the {@code SizeConverter} instance.
+		 *
+		 * @return the {@code SizeConverter} instance
+		 */
+		public static StyleConverter<String, Size> getInstance() {
+			return Holder.INSTANCE;
+		}
+
+		private SizeConverter() {
+			super();
+		}
+
+		@Override
+		public Size convert(ParsedValue<String, Size> value, Font font) {
+			try {
+				double[] sizes = Arrays.stream(value.getValue().split(" "))
+						.mapToDouble(Double::parseDouble)
+						.toArray();
+				return Size.of(sizes[0], sizes[1]);
+			} catch (Exception ex) {
+				System.out.println(ex.getMessage());
+				return null;
+			}
+		}
+
+		@Override
+		public String toString() {
+			return "SizeConverter";
+		}
+	}
+}

+ 48 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/styleable/StyleableStringProperty.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.styleable;
+
+import javafx.css.CssMetaData;
+import javafx.css.SimpleStyleableStringProperty;
+import javafx.css.StyleOrigin;
+import javafx.css.Styleable;
+
+public class StyleableStringProperty extends SimpleStyleableStringProperty {
+
+	public StyleableStringProperty(CssMetaData<? extends Styleable, String> cssMetaData) {
+		super(cssMetaData);
+	}
+
+	public StyleableStringProperty(CssMetaData<? extends Styleable, String> cssMetaData, String initialValue) {
+		super(cssMetaData, initialValue);
+	}
+
+	public StyleableStringProperty(CssMetaData<? extends Styleable, String> cssMetaData, Object bean, String name) {
+		super(cssMetaData, bean, name);
+	}
+
+	public StyleableStringProperty(CssMetaData<? extends Styleable, String> cssMetaData, Object bean, String name, String initialValue) {
+		super(cssMetaData, bean, name, initialValue);
+	}
+
+	@Override
+	public StyleOrigin getStyleOrigin() {
+		return StyleOrigin.USER_AGENT;
+	}
+}

+ 212 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedBooleanProperty.java

@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for boolean values.
+ */
+public class SynchronizedBooleanProperty extends ReadOnlyBooleanWrapper implements SynchronizedProperty<Boolean> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedBooleanProperty() {
+		initialize();
+	}
+
+	public SynchronizedBooleanProperty(boolean initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedBooleanProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedBooleanProperty(Object bean, String name, boolean initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(Boolean value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional binding with the given observable.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends Boolean> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source);
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<Boolean> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this).addSource(
+				new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<Boolean> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} flag value and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `BindingManager.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		MFXBindings bindings = MFXBindings.instance();
+		return bindings.isBound(this) && !bindings.isIgnoreBinding(this);
+	}
+}

+ 212 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedDoubleProperty.java

@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyDoubleWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for double values.
+ */
+public class SynchronizedDoubleProperty extends ReadOnlyDoubleWrapper implements SynchronizedProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedDoubleProperty() {
+		initialize();
+	}
+
+	public SynchronizedDoubleProperty(double initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedDoubleProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedDoubleProperty(Object bean, String name, double initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(Number value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value.doubleValue());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional bindings with the given observable.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends Number> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source).get();
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<Number> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this)
+				.addSource(new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<Number> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `MFXBindings.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		return MFXBindings.instance().isBound(this) && !MFXBindings.instance().isIgnoreBinding(this);
+	}
+}

+ 212 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedFloatProperty.java

@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyFloatWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for float values.
+ */
+public class SynchronizedFloatProperty extends ReadOnlyFloatWrapper implements SynchronizedProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedFloatProperty() {
+		initialize();
+	}
+
+	public SynchronizedFloatProperty(float initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedFloatProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedFloatProperty(Object bean, String name, float initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(Number value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value.floatValue());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional bindings with the given observable.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends Number> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source).get();
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<Number> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this)
+				.addSource(new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<Number> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `MFXBindings.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		return MFXBindings.instance().isBound(this) && !MFXBindings.instance().isIgnoreBinding(this);
+	}
+}

+ 212 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedIntegerProperty.java

@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyIntegerWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for integer values.
+ */
+public class SynchronizedIntegerProperty extends ReadOnlyIntegerWrapper implements SynchronizedProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedIntegerProperty() {
+		initialize();
+	}
+
+	public SynchronizedIntegerProperty(int initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedIntegerProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedIntegerProperty(Object bean, String name, int initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(Number value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value.intValue());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional bindings with the given observable.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends Number> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source).get();
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<Number> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this)
+				.addSource(new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<Number> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} flag value and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `MFXBindings.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		return MFXBindings.instance().isBound(this) && !MFXBindings.instance().isIgnoreBinding(this);
+	}
+}

+ 211 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedLongProperty.java

@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyLongWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for long values.
+ */
+public class SynchronizedLongProperty extends ReadOnlyLongWrapper implements SynchronizedProperty<Number> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedLongProperty() {
+		initialize();
+	}
+
+	public SynchronizedLongProperty(long initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedLongProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedLongProperty(Object bean, String name, long initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(Number value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value.longValue());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional bindings with the given observable.
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends Number> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source).get();
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<Number> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this).addSource(
+				new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<Number> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `MFXBindings.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		return MFXBindings.instance().isBound(this) && !MFXBindings.instance().isIgnoreBinding(this);
+	}
+}

+ 214 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedObjectProperty.java

@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for generic values.
+ *
+ * @param <T> the type of the wrapped Object
+ */
+public class SynchronizedObjectProperty<T> extends ReadOnlyObjectWrapper<T> implements SynchronizedProperty<T> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedObjectProperty() {
+		initialize();
+	}
+
+	public SynchronizedObjectProperty(T initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedObjectProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedObjectProperty(Object bean, String name, T initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(T value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional bindings with the given observable.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends T> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source).get();
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<T> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this).addSource(
+				new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<T> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} flag value and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `MFXBindings.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		return MFXBindings.instance().isBound(this) && !MFXBindings.instance().isIgnoreBinding(this);
+	}
+}

+ 212 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/base/properties/synced/SynchronizedStringProperty.java

@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.base.properties.synced;
+
+import io.github.palexdev.mfxcore.base.bindings.MFXBindings;
+import io.github.palexdev.mfxcore.base.bindings.Source;
+import io.github.palexdev.mfxcore.base.properties.base.SynchronizedProperty;
+import io.github.palexdev.mfxcore.observables.When;
+import javafx.beans.property.Property;
+import javafx.beans.property.ReadOnlyBooleanProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
+import javafx.beans.property.ReadOnlyStringWrapper;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Implementation of {@link SynchronizedProperty} for String values.
+ */
+public class SynchronizedStringProperty extends ReadOnlyStringWrapper implements SynchronizedProperty<String> {
+	//================================================================================
+	// Properties
+	//================================================================================
+	private final ReadOnlyBooleanWrapper waiting = new ReadOnlyBooleanWrapper();
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	public SynchronizedStringProperty() {
+		initialize();
+	}
+
+	public SynchronizedStringProperty(String initialValue) {
+		super(initialValue);
+		initialize();
+	}
+
+	public SynchronizedStringProperty(Object bean, String name) {
+		super(bean, name);
+		initialize();
+	}
+
+	public SynchronizedStringProperty(Object bean, String name, String initialValue) {
+		super(bean, name, initialValue);
+		initialize();
+	}
+
+	//================================================================================
+	// Methods
+	//================================================================================
+
+	/**
+	 * Adds a listener to the property by calling {@link When#onChanged(ObservableValue)}
+	 * to call {@link #fireValueChangedEvent()} when the property is awakened, {@link #awake()}.
+	 */
+	private void initialize() {
+		When.onChanged(waiting)
+				.then((oldValue, newValue) -> {
+					if (!newValue) fireValueChangedEvent();
+				})
+				.listen();
+	}
+
+	//================================================================================
+	// Implemented/Overridden Methods
+	//================================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setAndWait(String value, ObservableValue<?> observable) {
+		if (!Helper.check(this, value, observable)) return;
+
+		waiting.set(true);
+		When.onChanged(observable)
+				.then((oldValue, newValue) -> awake())
+				.oneShot()
+				.listen();
+		set(value);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isWaiting() {
+		return waiting.get();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ReadOnlyBooleanProperty waiting() {
+		return waiting.getReadOnlyProperty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void awake() {
+		waiting.set(false);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * <p></p>
+	 * Overridden to not fire a change event if {@link #waiting()} is true.
+	 */
+	@Override
+	protected void fireValueChangedEvent() {
+		if (isWaiting()) return;
+		super.fireValueChangedEvent();
+	}
+
+	//================================================================================
+	// Binding
+	//================================================================================
+
+	/**
+	 * Creates a unidirectional bindings with the given observable.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound it is automatically unbound before bindings to the new observable.
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bind(ObservableValue<? extends String> source) {
+		if (this == source) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bind(this).source(source).get();
+	}
+
+	/**
+	 * Creates a bidirectional bindings between this property and the given property.
+	 * <p>
+	 * The binding is created using the new {@link MFXBindings} mechanism.
+	 * <p></p>
+	 * If the property is already bound unidirectionally it is automatically unbound.
+	 * <p>
+	 * If the property is already bound bidirectionally it won't be automatically unbound, just like JavaFX,
+	 * this way you can have multiple bidirectional bindings
+	 *
+	 * @throws IllegalArgumentException if the given observable is the property itself
+	 * @see MFXBindings
+	 */
+	@Override
+	public void bindBidirectional(Property<String> other) {
+		if (this == other) {
+			throw new IllegalArgumentException("Cannot bind to itself!");
+		}
+
+		if (isBound()) unbind();
+		MFXBindings.instance().bindBidirectional(this)
+				.addSource(new Source<>(other).implicit(this, other)).get();
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbind(ObservableValue)}.
+	 */
+	@Override
+	public void unbind() {
+		MFXBindings.instance().unbind(this);
+	}
+
+	/**
+	 * Overridden to call {@link MFXBindings#unbindBidirectional(ObservableValue, ObservableValue)}.
+	 */
+	@Override
+	public void unbindBidirectional(Property<String> other) {
+		MFXBindings.instance().unbindBidirectional(this, other);
+	}
+
+	/**
+	 * Delegate method for {@link MFXBindings#disposeBidirectional(ObservableValue)}.
+	 */
+	public void clearBidirectional() {
+		MFXBindings.instance().disposeBidirectional(this);
+	}
+
+	/**
+	 * Overridden to check the {@link MFXBindings#isBound(ObservableValue)} flag value and {@link MFXBindings#isIgnoreBinding(ObservableValue)}.
+	 *
+	 * @return true only if `MFXBindings.isBound()` is true and `isIgnoreBound()` is false
+	 */
+	@Override
+	public boolean isBound() {
+		return MFXBindings.instance().isBound(this) && !MFXBindings.instance().isIgnoreBinding(this);
+	}
+}

+ 72 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/builders/CornerRadiusBuilder.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.builders;
+
+import javafx.scene.layout.CornerRadii;
+
+/**
+ * Convenience class to build {@link CornerRadii} objects.
+ */
+public class CornerRadiusBuilder {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	private CornerRadiusBuilder() {
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+	public static CornerRadii all(double topRightBottomLeft) {
+		return new CornerRadii(topRightBottomLeft);
+	}
+
+	public static CornerRadii none() {
+		return CornerRadii.EMPTY;
+	}
+
+	public static CornerRadii top(double topLeft) {
+		return new CornerRadii(topLeft, 0, 0, 0, false);
+	}
+
+	public static CornerRadii right(double topRight) {
+		return new CornerRadii(0, topRight, 0, 0, false);
+	}
+
+	public static CornerRadii bottom(double bottomRight) {
+		return new CornerRadii(0, 0, bottomRight, 0, false);
+	}
+
+	public static CornerRadii left(double bottomLeft) {
+		return new CornerRadii(0, 0, 0, bottomLeft, false);
+	}
+
+	public static CornerRadii of(double topLeft, double topRight) {
+		return new CornerRadii(topLeft, topRight, 0, 0, false);
+	}
+
+	public static CornerRadii of(double topLeft, double topRight, double bottomRight) {
+		return new CornerRadii(topLeft, topRight, bottomRight, 0, false);
+	}
+
+	public static CornerRadii of(double topLeft, double topRight, double bottomRight, double bottomLeft) {
+		return new CornerRadii(topLeft, topRight, bottomRight, bottomLeft, false);
+	}
+}

+ 72 - 0
modules/core/src/main/java/io/github/palexdev/mfxcore/builders/InsetsBuilder.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 Parisi Alessandro
+ * This file is part of MFXCore (https://github.com/palexdev/MFXCore).
+ *
+ * MFXCore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MFXCore is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MFXCore.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package io.github.palexdev.mfxcore.builders;
+
+import javafx.geometry.Insets;
+
+/**
+ * Convenience class to build {@link Insets} objects.
+ */
+public class InsetsBuilder {
+
+	//================================================================================
+	// Constructors
+	//================================================================================
+	private InsetsBuilder() {
+	}
+
+	//================================================================================
+	// Static Methods
+	//================================================================================
+	public static Insets all(double topRightBottomLeft) {
+		return new Insets(topRightBottomLeft);
+	}
+
+	public static Insets none() {
+		return Insets.EMPTY;
+	}
+
+	public static Insets top(double top) {
+		return new Insets(top, 0, 0, 0);
+	}
+
+	public static Insets right(double right) {
+		return new Insets(0, right, 0, 0);
+	}
+
+	public static Insets bottom(double bottom) {
+		return new Insets(0, 0, bottom, 0);
+	}
+
+	public static Insets left(double left) {
+		return new Insets(0, 0, 0, left);
+	}
+
+	public static Insets of(double top, double right) {
+		return new Insets(top, right, 0, 0);
+	}
+
+	public static Insets of(double top, double right, double bottom) {
+		return new Insets(top, right, bottom, 0);
+	}
+
+	public static Insets of(double top, double right, double bottom, double left) {
+		return new Insets(top, right, bottom, left);
+	}
+}

Some files were not shown because too many files changed in this diff