Repository: JodaOrg/joda-beans Branch: main Commit: ada2a8fae2c5 Files: 427 Total size: 3.6 MB Directory structure: gitextract_08ef56yp/ ├── .coderabbit.yaml ├── .github/ │ ├── FUNDING.yml │ ├── SECURITY.md │ ├── dependabot.yml │ ├── maven-settings.xml │ └── workflows/ │ ├── build.yml │ ├── release.yml │ └── website.yml ├── .gitignore ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── RELEASE-NOTES.txt ├── pom.xml └── src/ ├── changes/ │ └── changes.xml ├── main/ │ ├── assembly/ │ │ └── dist.xml │ ├── checkstyle/ │ │ └── checkstyle.xml │ ├── java/ │ │ ├── module-info.java │ │ └── org/ │ │ └── joda/ │ │ └── beans/ │ │ ├── Bean.java │ │ ├── BeanBuilder.java │ │ ├── BeanIterator.java │ │ ├── DynamicBean.java │ │ ├── DynamicMetaBean.java │ │ ├── ImmutableBean.java │ │ ├── JodaBeanUtils.java │ │ ├── MetaBean.java │ │ ├── MetaBeanProvider.java │ │ ├── MetaBeans.java │ │ ├── MetaProperty.java │ │ ├── MetaProvider.java │ │ ├── Property.java │ │ ├── PropertyPath.java │ │ ├── PropertyStyle.java │ │ ├── ResolvedType.java │ │ ├── TypedMetaBean.java │ │ ├── gen/ │ │ │ ├── BeanCodeGen.java │ │ │ ├── BeanCodeGenException.java │ │ │ ├── BeanData.java │ │ │ ├── BeanDefinition.java │ │ │ ├── BeanGen.java │ │ │ ├── BeanGenConfig.java │ │ │ ├── BeanParser.java │ │ │ ├── BuilderGen.java │ │ │ ├── CopyGen.java │ │ │ ├── DerivedProperty.java │ │ │ ├── GetterGen.java │ │ │ ├── ImmutableConstructor.java │ │ │ ├── ImmutableDefaults.java │ │ │ ├── ImmutablePreBuild.java │ │ │ ├── ImmutableValidator.java │ │ │ ├── PropertyData.java │ │ │ ├── PropertyDefinition.java │ │ │ ├── PropertyGen.java │ │ │ ├── PropertyParser.java │ │ │ ├── SetterGen.java │ │ │ └── package-info.java │ │ ├── impl/ │ │ │ ├── BasicBean.java │ │ │ ├── BasicBeanBuilder.java │ │ │ ├── BasicImmutableBeanBuilder.java │ │ │ ├── BasicMetaBean.java │ │ │ ├── BasicMetaProperty.java │ │ │ ├── BasicProperty.java │ │ │ ├── BasicPropertyMap.java │ │ │ ├── BufferingBeanBuilder.java │ │ │ ├── RecordBean.java │ │ │ ├── RecordBeanBuilder.java │ │ │ ├── RecordMetaBean.java │ │ │ ├── RecordMetaProperty.java │ │ │ ├── StandaloneMetaProperty.java │ │ │ ├── direct/ │ │ │ │ ├── DirectBean.java │ │ │ │ ├── DirectBeanBuilder.java │ │ │ │ ├── DirectFieldsBeanBuilder.java │ │ │ │ ├── DirectMetaBean.java │ │ │ │ ├── DirectMetaProperty.java │ │ │ │ ├── DirectMetaPropertyMap.java │ │ │ │ ├── DirectPrivateBeanBuilder.java │ │ │ │ ├── MinimalMetaBean.java │ │ │ │ ├── MinimalMetaProperty.java │ │ │ │ └── package-info.java │ │ │ ├── flexi/ │ │ │ │ ├── FlexiBean.java │ │ │ │ ├── FlexiBeanBuilder.java │ │ │ │ ├── FlexiMetaBean.java │ │ │ │ ├── FlexiMetaProperty.java │ │ │ │ └── package-info.java │ │ │ ├── light/ │ │ │ │ ├── LightBeanBuilder.java │ │ │ │ ├── LightMetaBean.java │ │ │ │ ├── LightMetaProperty.java │ │ │ │ ├── PropertyGetter.java │ │ │ │ ├── PropertySetter.java │ │ │ │ └── package-info.java │ │ │ ├── map/ │ │ │ │ ├── MapBean.java │ │ │ │ ├── MapBeanBuilder.java │ │ │ │ ├── MapBeanMetaProperty.java │ │ │ │ ├── MapMetaBean.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── reflection/ │ │ │ ├── ReflectiveMetaBean.java │ │ │ ├── ReflectiveMetaProperty.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── ser/ │ │ │ ├── CollectSerIteratorFactory.java │ │ │ ├── DefaultDeserializer.java │ │ │ ├── GuavaSerIteratorFactory.java │ │ │ ├── JodaBeanMimeType.java │ │ │ ├── JodaBeanSer.java │ │ │ ├── JodaBeanSerFormat.java │ │ │ ├── JodaBeanSmartReader.java │ │ │ ├── LenientDeserializer.java │ │ │ ├── LinkedByteArrayOutputStream.java │ │ │ ├── SerCategory.java │ │ │ ├── SerDeserializer.java │ │ │ ├── SerDeserializerProvider.java │ │ │ ├── SerDeserializers.java │ │ │ ├── SerIterable.java │ │ │ ├── SerIterator.java │ │ │ ├── SerIteratorFactory.java │ │ │ ├── SerOptional.java │ │ │ ├── SerTypeMapper.java │ │ │ ├── bin/ │ │ │ │ ├── AbstractBinReader.java │ │ │ │ ├── AbstractBinWriter.java │ │ │ │ ├── BeanPack.java │ │ │ │ ├── BeanPackInput.java │ │ │ │ ├── BeanPackOutput.java │ │ │ │ ├── BeanPackVisualizer.java │ │ │ │ ├── BeanReferences.java │ │ │ │ ├── JodaBeanBinFormat.java │ │ │ │ ├── JodaBeanBinReader.java │ │ │ │ ├── JodaBeanBinWriter.java │ │ │ │ ├── JodaBeanPackedBinReader.java │ │ │ │ ├── JodaBeanPackedBinWriter.java │ │ │ │ ├── JodaBeanReferencingBinReader.java │ │ │ │ ├── JodaBeanReferencingBinWriter.java │ │ │ │ ├── JodaBeanStandardBinReader.java │ │ │ │ ├── JodaBeanStandardBinWriter.java │ │ │ │ ├── MsgPack.java │ │ │ │ ├── MsgPackInput.java │ │ │ │ ├── MsgPackOutput.java │ │ │ │ ├── MsgPackVisualizer.java │ │ │ │ └── package-info.java │ │ │ ├── json/ │ │ │ │ ├── AbstractJsonReader.java │ │ │ │ ├── JodaBeanJsonNumberFormat.java │ │ │ │ ├── JodaBeanJsonReader.java │ │ │ │ ├── JodaBeanJsonWriter.java │ │ │ │ ├── JodaBeanSimpleJsonReader.java │ │ │ │ ├── JodaBeanSimpleJsonWriter.java │ │ │ │ ├── JsonEvent.java │ │ │ │ ├── JsonInput.java │ │ │ │ ├── JsonOutput.java │ │ │ │ └── package-info.java │ │ │ ├── map/ │ │ │ │ ├── JodaBeanSimpleMapReader.java │ │ │ │ ├── JodaBeanSimpleMapWriter.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── xml/ │ │ │ ├── JodaBeanXml.java │ │ │ ├── JodaBeanXmlReader.java │ │ │ ├── JodaBeanXmlWriter.java │ │ │ └── package-info.java │ │ └── test/ │ │ ├── BeanAssert.java │ │ ├── BeanComparisonError.java │ │ ├── JodaBeanTests.java │ │ └── package-info.java │ └── resources/ │ └── org/ │ └── joda/ │ └── beans/ │ └── gen/ │ ├── guava.ini │ └── jdk.ini ├── site/ │ ├── markdown/ │ │ ├── enterprise.md │ │ ├── index.md │ │ ├── licensecover.md │ │ ├── migration.md │ │ ├── related.md │ │ ├── userguide-codegen.md │ │ ├── userguide-serialization.md │ │ └── userguide.md │ ├── resources/ │ │ ├── css/ │ │ │ └── site.css │ │ └── download.html │ └── site.xml └── test/ ├── java/ │ └── org/ │ └── joda/ │ └── beans/ │ ├── Examples.java │ ├── TestAddress.java │ ├── TestArray.java │ ├── TestBasicBean.java │ ├── TestBeanCodeGenException.java │ ├── TestBeanIterator.java │ ├── TestClone.java │ ├── TestCompanyAddress.java │ ├── TestFinalFieldBean.java │ ├── TestFlexiBean.java │ ├── TestImmutable.java │ ├── TestJodaBeanUtils.java │ ├── TestLight.java │ ├── TestMapBean.java │ ├── TestMetaBean.java │ ├── TestMetaBeanProvider.java │ ├── TestMetaBeans.java │ ├── TestMetaInvoke.java │ ├── TestMinimal.java │ ├── TestMutableDerived.java │ ├── TestMutableListBeans.java │ ├── TestOptionalBean.java │ ├── TestPair.java │ ├── TestPerson.java │ ├── TestPropertyPath.java │ ├── TestPropertyStyle.java │ ├── TestRecordBean.java │ ├── TestReflective.java │ ├── TestResolvedType.java │ ├── TestResult.java │ ├── TestSubBean.java │ ├── TestValidateBean.java │ ├── sample/ │ │ ├── AbstractResult.java │ │ ├── Address.java │ │ ├── AddressResult.java │ │ ├── ClassAnnotation.java │ │ ├── ClonePerson.java │ │ ├── Company.java │ │ ├── CompanyAddress.java │ │ ├── CompanyAddressMidResult.java │ │ ├── CompanyAddressResult.java │ │ ├── ComplexAnnotation.java │ │ ├── Documentation.java │ │ ├── DocumentationHolder.java │ │ ├── DoubleGenericsComplexExtendsSuperTwoGenerics.java │ │ ├── DoubleGenericsNoExtendsNoSuper.java │ │ ├── DoubleGenericsSimpleSuper.java │ │ ├── DoubleGenericsWithExtendsNoSuper.java │ │ ├── DoubleGenericsWithExtendsSuperNoGenerics.java │ │ ├── DoubleGenericsWithExtendsSuperOneGeneric.java │ │ ├── DoubleGenericsWithExtendsSuperTwoGenerics.java │ │ ├── FieldNamesImmutable.java │ │ ├── FieldNamesImmutableMinimal.java │ │ ├── FieldNamesLight.java │ │ ├── FieldNamesMutable.java │ │ ├── FieldNamesMutableMinimal.java │ │ ├── FinalFieldBean.java │ │ ├── GenericAllFinal.java │ │ ├── GenericArray.java │ │ ├── GenericInterfaceBase.java │ │ ├── GenericInterfaceChild.java │ │ ├── GenericInterfaceImpl.java │ │ ├── GenericInterfaceMid.java │ │ ├── GenericSubWrapper.java │ │ ├── GenericUnionType.java │ │ ├── GenericWrapperDocumentation.java │ │ ├── IKey.java │ │ ├── INamedKey.java │ │ ├── IPerson.java │ │ ├── ImmAddress.java │ │ ├── ImmArrays.java │ │ ├── ImmClone.java │ │ ├── ImmComplexAnnotation.java │ │ ├── ImmDefault.java │ │ ├── ImmDeprecated.java │ │ ├── ImmDocumentationHolder.java │ │ ├── ImmDocumentationResult.java │ │ ├── ImmDoubleArray.java │ │ ├── ImmDoubleFloat.java │ │ ├── ImmEmpty.java │ │ ├── ImmFieldGetter.java │ │ ├── ImmGeneric.java │ │ ├── ImmGenericArray.java │ │ ├── ImmGenericCollections.java │ │ ├── ImmGenericLinkedRefs.java │ │ ├── ImmGenericNonFinal.java │ │ ├── ImmGuava.java │ │ ├── ImmJodaConvertBean.java │ │ ├── ImmJodaConvertWrapper.java │ │ ├── ImmKey.java │ │ ├── ImmKeyDeserializer.java │ │ ├── ImmKeyHolder.java │ │ ├── ImmKeyHolderDeserializer.java │ │ ├── ImmKeyList.java │ │ ├── ImmMappedKey.java │ │ ├── ImmMinimalMetaBuilder.java │ │ ├── ImmMinimalPrivateBuilder.java │ │ ├── ImmNamedKey.java │ │ ├── ImmOptional.java │ │ ├── ImmOptionalMeta.java │ │ ├── ImmPackageScoped.java │ │ ├── ImmPair.java │ │ ├── ImmPerson.java │ │ ├── ImmPersonAbstract.java │ │ ├── ImmPersonNonFinal.java │ │ ├── ImmPrivateMeta.java │ │ ├── ImmSubPersonFromAbstract.java │ │ ├── ImmSubPersonNonFinal.java │ │ ├── ImmSubSubPersonFinal.java │ │ ├── ImmTolerance.java │ │ ├── ImmTreeNode.java │ │ ├── ImmTypes.java │ │ ├── ImmUnusedGeneric.java │ │ ├── JodaConvertBean.java │ │ ├── JodaConvertInterface.java │ │ ├── JodaConvertWrapper.java │ │ ├── LightEmpty.java │ │ ├── LightImmutable.java │ │ ├── LightImmutableGeneric.java │ │ ├── LightImmutableSimple.java │ │ ├── LightMutable.java │ │ ├── LightMutableGeneric.java │ │ ├── LightMutableSimple.java │ │ ├── MetaBeanLoad.java │ │ ├── MidAbstractResult.java │ │ ├── MinimalEmpty.java │ │ ├── MinimalImmutable.java │ │ ├── MinimalImmutableGeneric.java │ │ ├── MinimalImmutableSimple.java │ │ ├── MinimalManualBuilder.java │ │ ├── MinimalMutable.java │ │ ├── MinimalMutableGeneric.java │ │ ├── MinimalMutableGenericSimple.java │ │ ├── MinimalMutableSimple.java │ │ ├── MutableBaseBean.java │ │ ├── MutableDeprecated.java │ │ ├── MutableDerived.java │ │ ├── MutableDerivedBean.java │ │ ├── MutableEmptyBase.java │ │ ├── MutableListFinalBean.java │ │ ├── MutableListNonFinalBean.java │ │ ├── MutableOptional.java │ │ ├── MutableTypes.java │ │ ├── NoClone.java │ │ ├── NoGenEquals.java │ │ ├── NoGenToString.java │ │ ├── NoProperties.java │ │ ├── Pair.java │ │ ├── PairBuilder.java │ │ ├── PairDeserializer.java │ │ ├── PairManualInnerBuilder.java │ │ ├── PairManualTopLevelBuilder.java │ │ ├── Person.java │ │ ├── PersonDocumentation.java │ │ ├── PrimitiveBean.java │ │ ├── PropertyDefBean.java │ │ ├── RWOnlyBean.java │ │ ├── RecordStrIntPair.java │ │ ├── ReflectiveMutable.java │ │ ├── Risk.java │ │ ├── RiskFactory.java │ │ ├── RiskLevel.java │ │ ├── RiskPerception.java │ │ ├── SimpleAnnotation.java │ │ ├── SimpleJson.java │ │ ├── SimpleName.java │ │ ├── SimplePerson.java │ │ ├── SimplePersonWithBuilderFinal.java │ │ ├── SimplePersonWithBuilderNonFinal.java │ │ ├── SimpleSubPersonWithBuilderFinal.java │ │ ├── SimpleSubPersonWithBuilderNonFinal.java │ │ ├── SubDecimal.java │ │ ├── SubPerson.java │ │ ├── SubValidateBean.java │ │ ├── SubWrapper.java │ │ ├── TestRWOnlyBean.java │ │ ├── TupleFinal.java │ │ ├── TupleImmutable.java │ │ ├── TupleNonFinal.java │ │ ├── TupleSub.java │ │ ├── TweakedPair.java │ │ ├── UserAccount.java │ │ ├── ValidateBean.java │ │ ├── ValidateBeanCheck.java │ │ ├── WeirdFormat.java │ │ ├── Wrapper.java │ │ └── WrapperToDoubleGenerics.java │ ├── ser/ │ │ ├── AtomicReference.java │ │ ├── BigDecimal.java │ │ ├── Normal.java │ │ ├── SerTestHelper.java │ │ ├── TestJodaBeanBinFormat.java │ │ ├── TestLinkedByteArrayOutputStream.java │ │ ├── TestSerDeserializerProvider.java │ │ ├── TestSerTypeMapper.java │ │ ├── TestSerializeSmartReader.java │ │ ├── bin/ │ │ │ ├── TestBinPerformance.java │ │ │ ├── TestSerializePackedBin.java │ │ │ ├── TestSerializeReferencingBin.java │ │ │ └── TestSerializeStandardBin.java │ │ ├── json/ │ │ │ ├── TestJsonInput.java │ │ │ ├── TestJsonOutput.java │ │ │ ├── TestJsonPerformance.java │ │ │ ├── TestSerializeJson.java │ │ │ └── TestSerializeJsonSimple.java │ │ ├── lowerCase.java │ │ ├── map/ │ │ │ └── TestSerializeSimpleMap.java │ │ └── xml/ │ │ ├── MockRenameDeserializer.java │ │ ├── MockSemanticChangeDeserializer.java │ │ ├── MockTypeChangeDeserializer.java │ │ ├── TestDeserializeXml.java │ │ └── TestSerializeXml.java │ └── test/ │ ├── TestBeanAssert.java │ └── TestCoverage.java └── resources/ ├── META-INF/ │ └── org/ │ └── joda/ │ └── beans/ │ └── JodaBeans.ini └── org/ └── joda/ └── beans/ └── ser/ ├── Address.xml ├── Address1.packbinstr ├── Address2.binstr ├── Address2.json ├── Address2.simplejson ├── Collections.xml ├── Collections1.binstr ├── Collections1.json ├── Collections1.packbinstr ├── Collections1.refbinstr ├── Collections2.binstr ├── Collections2.json ├── Collections2.simplejson ├── ImmAddress.xml ├── ImmAddress1.binstr ├── ImmAddress1.json ├── ImmAddress1.packbinstr ├── ImmAddress1.refbinstr ├── ImmAddress1.simplejson ├── ImmAddress2.binstr ├── ImmAddress2.json ├── ImmAddress2.simplejson ├── ImmAddressCached1.packbinstr ├── ImmArrays1.binstr ├── ImmArrays1.json ├── ImmArrays1.packbinstr ├── ImmArrays1.refbinstr ├── ImmArrays1.simplejson ├── ImmArrays2.binstr ├── ImmArrays2.json ├── ImmArrays2.simplejson ├── ImmOptional.xml ├── ImmOptional1.packbinstr ├── ImmOptional1.refbinstr ├── ImmOptional2.binstr ├── ImmOptional2.json ├── ImmOptional2.simplejson └── SimpleJson2.simplejson ================================================ FILE CONTENTS ================================================ ================================================ FILE: .coderabbit.yaml ================================================ language: en-GB tone_instructions: '' early_access: false enable_free_tier: true reviews: profile: chill request_changes_workflow: true high_level_summary: true high_level_summary_placeholder: '@coderabbitai summary' auto_title_placeholder: '@coderabbitai' review_status: true commit_status: true poem: false collapse_walkthrough: true sequence_diagrams: false changed_files_summary: true labeling_instructions: [] path_filters: - '**/*' - '**/gen/**' - '!**/test/**/gen/**' - '!**/.git/**' - '!**/target/**' path_instructions: - path: '**/*.java' instructions: | - Review code using Java 21 standards, taking into account the rules defined by `src/main/checkstyle/checkstyle.xml`. - Validate that code indentation uses spaces, not tabs, with an indent of multiple of 4. - Validate that immutable local variables are not annotated with `final` unless the variable is required for use in an inner class. - Favour use of `var` keyword for type declarations. `var` may also be used when the value is a cast `null`. - Use a coding standard where multi-line expressions have operators and tenary separators at the end of line. - Propose changes that only use the Java 21 API, not the API of Guava. - The pattern matching `instanceof` expression safely handles `null`, returning `false`. - path: '**/main/java/**/*.java' instructions: | - This project is mature and must provide a stable backwards-compatible public Java API. - In the 'Walkthrough' section, you must always provide a list of up to 25 changes to the public Java API that will affect end users. If there are no changes, you must explicitly state that there are no changes to the public Java API in this PR. The public Java API is defined as public and protected methods on public classes, plus the file `module-info.java`. Provide the list by deeply analysing code flow, which incudes analysing code flow through private methods and calls to Guava and Java 21. Changes to be reported on include: - New or removed methods in the public Java API - Changes to method return types or parameter types in the public Java API - Changes to method behaviour in the public Java API that might affect consumers - This project uses `System.out.println` instead of logging - This project tends to prefer `for` loops to streams for performance reasons, however either form is acceptable. Do not make suggestions to change between streams and for loops or vice versa. - path: '**/test/java/**/*.java' instructions: | For test code, focus on: - Correctness of test assertions - Test coverage of edge cases - Clear test naming and documentation - Encourage test methods to be package-scoped where possible - Be more lenient with code style and minor optimisations abort_on_close: true auto_review: enabled: true auto_incremental_review: true ignore_title_keywords: [] labels: [] drafts: false base_branches: - 'main' tools: shellcheck: enabled: true ruff: enabled: false markdownlint: enabled: true github-checks: enabled: true timeout_ms: 90000 languagetool: enabled: true enabled_only: false level: default enabled_rules: [] disabled_rules: - EN_UNPAIRED_BRACKETS enabled_categories: [] disabled_categories: - TYPOS - TYPOGRAPHY - CASING biome: enabled: true hadolint: enabled: false swiftlint: enabled: true phpstan: enabled: false level: default golangci-lint: enabled: false yamllint: enabled: true gitleaks: enabled: true checkov: enabled: false detekt: enabled: false eslint: enabled: true rubocop: enabled: false buf: enabled: false regal: enabled: false actionlint: enabled: true pmd: enabled: true cppcheck: enabled: false semgrep: enabled: true circleci: enabled: true ast-grep: packages: [] rule_dirs: [] util_dirs: [] essential_rules: true chat: auto_reply: true knowledge_base: opt_out: false learnings: scope: auto issues: scope: auto jira: project_keys: [] linear: team_keys: [] pull_requests: scope: auto ================================================ FILE: .github/FUNDING.yml ================================================ github: jodastephen open_collective: joda tidelift: maven/org.joda:joda-beans # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository ================================================ FILE: .github/SECURITY.md ================================================ # Security Policy ## Supported Versions If a security issue occurs, only the latest versions of v3.x and v2.x are guaranteed to be patched. Consideration will be given to updating the v1.x line, however this is not guaranteed. ## Reporting a Vulnerability To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. ================================================ FILE: .github/dependabot.yml ================================================ # Dependabot config version: 2 updates: - package-ecosystem: "maven" directory: "/" schedule: interval: weekly time: "02:30" open-pull-requests-limit: 20 ================================================ FILE: .github/maven-settings.xml ================================================ central-publish ${env.MAVEN_CENTRAL_USERNAME} ${env.MAVEN_CENTRAL_PASSWORD} github ${env.GITHUB_TOKEN} ================================================ FILE: .github/workflows/build.yml ================================================ name: Build on: push: branches: - '*' pull_request: branches: - 'main' schedule: - cron: '41 19 * * 2' permissions: contents: read jobs: build: permissions: security-events: write # for github/codeql-action runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v4 with: java-version: 21 distribution: 'temurin' cache: 'maven' - name: Maven version run: | mkdir -p ./.mvn echo "-e" >> ./.mvn/maven.config echo "-B" >> ./.mvn/maven.config echo "-ntp" >> ./.mvn/maven.config echo "-DtrimStackTrace=false" >> ./.mvn/maven.config echo "--settings" >> ./.mvn/maven.config echo "$( pwd )/.github/maven-settings.xml" >> ./.mvn/maven.config mvn --version mkdir -p target #------------------------------------------------------------------------ - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: java - name: Maven build run: | mvn install site -Doss.build - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 ================================================ FILE: .github/workflows/release.yml ================================================ name: Release on: push: tags: - 'release*' permissions: contents: write jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: token: ${{ secrets.PERSONAL_GITHUB_TOKEN }} ref: "main" fetch-tags: true - name: Setup git run: | git config --global user.name "Stephen Colebourne (CI)" git config --global user.email "scolebourne@joda.org" - name: Set up JDK uses: actions/setup-java@v4 with: java-version: 21 distribution: 'temurin' cache: 'maven' - name: Maven version run: | mkdir -p ./.mvn echo "-e" >> ./.mvn/maven.config echo "-B" >> ./.mvn/maven.config echo "-ntp" >> ./.mvn/maven.config echo "-DtrimStackTrace=false" >> ./.mvn/maven.config echo "--settings" >> ./.mvn/maven.config echo "$( pwd )/.github/maven-settings.xml" >> ./.mvn/maven.config mvn --version mkdir -p target #------------------------------------------------------------------------ - name: Maven install run: | mvn clean install - name: Maven release env: MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} MAVEN_GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} MAVEN_GPG_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} GITHUB_TOKEN: ${{ secrets.PERSONAL_GITHUB_TOKEN }} run: | mvn release:clean release:prepare release:perform - name: Update website run: | git tag websiterelease git push origin websiterelease - name: Delete release tag if: "always()" run: | git tag --delete "${GITHUB_REF_NAME}" || true git push --delete origin "${GITHUB_REF_NAME}" || true ================================================ FILE: .github/workflows/website.yml ================================================ name: Website on: push: tags: - 'website*' permissions: contents: write jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: token: ${{ secrets.PERSONAL_GITHUB_TOKEN }} ref: ${{ github.ref }} fetch-tags: true - name: Setup git run: | git config --global user.name "Stephen Colebourne (CI)" git config --global user.email "scolebourne@joda.org" - name: Set up JDK uses: actions/setup-java@v4 with: java-version: 21 distribution: 'temurin' cache: 'maven' - name: Maven version run: | mkdir -p ./.mvn echo "-e" >> ./.mvn/maven.config echo "-B" >> ./.mvn/maven.config echo "-ntp" >> ./.mvn/maven.config echo "-DtrimStackTrace=false" >> ./.mvn/maven.config echo "--settings" >> ./.mvn/maven.config echo "$( pwd )/.github/maven-settings.xml" >> ./.mvn/maven.config mvn --version mkdir -p target #------------------------------------------------------------------------ - name: Maven site run: | mvn install site - name: Checkout website uses: actions/checkout@v4 with: token: ${{ secrets.PERSONAL_GITHUB_TOKEN }} repository: JodaOrg/jodaorg.github.io path: target/jodaorg.github.io ref: "main" - name: Update website run: | cd target/jodaorg.github.io git status rm -rf joda-beans/ cp -R ../site joda-beans/ git add -A git status git commit --message "Update joda-beans from CI: $GITHUB_ACTION" git push origin main - name: Delete website tag if: "always()" run: | git tag --delete "${GITHUB_REF_NAME}" || true git push --delete origin "${GITHUB_REF_NAME}" || true ================================================ FILE: .gitignore ================================================ /bin/ /target/ *.log /tests/ /test-output/ .checkstyle .classpath .project /.settings/ .idea *.iml *.class ================================================ FILE: LICENSE.txt ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: NOTICE.txt ================================================ Joda Beans Copyright 2001-present Stephen Colebourne This product includes software developed by Joda.org (https://www.joda.org/). ================================================ FILE: README.md ================================================ Joda-Beans ------------ Joda-Beans provides a small framework that adds properties to Java, greatly enhancing JavaBeans. An API is provided that defines a bean and property model, together with a code generator to make it work in practice. The key concept is to allow each property on a bean to be accessed as an object. This enables technologies such as XPath, XML conversion, DB mappings, WebApp validation and Swing bindings. Joda-Beans is licensed under the business-friendly [Apache 2.0 licence](https://www.joda.org/joda-beans/licenses.html). ### Why Joda Beans? Joda-Beans has been created to plug a gap in the Java language - properties. The concept of properties is familiar to those coding in almost every other modern language. Java stands alone in its pursuit of the terrible JavaBean approach, and personally I believe that properties should have been added to Java before generics and closures. JavaBeans are typically created by manual coding or one-off IDE generation, such as by Eclipse. The same approach is taken to the creation of equals and hashCode methods. However, none of these approaches provides for a simple and fast mechanism to query a bean for the properties it exposes. Joda-Beans provides a solution. As a developer, you just write the fields much as you would today. Then you add annotations to the bean and properties. Finally, you run a code generator, which creates the get/set methods plus framework methods that allow the properties to be effectively queried. If you use Eclipse and the Joda-Beans Maven plugin, the bean will be regenerated automatically on save. A key point is that the code generator may be run again and again on the Java file, and is non-destructive. See these sample classes used for testing - [a simple user account class](https://github.com/JodaOrg/joda-beans/blob/v2.0/src/test/java/org/joda/beans/gen/UserAccount.java#L32), [example usage](https://github.com/JodaOrg/joda-beans/blob/v2.0/src/test/java/org/joda/beans/Examples.java#L22), [example of validation](https://github.com/JodaOrg/joda-beans/blob/v2.0/src/test/java/org/joda/beans/gen/ValidateBean.java#L33). ### Documentation Various documentation is available: * The [home page](https://www.joda.org/joda-beans/) * The helpful [user guide](https://www.joda.org/joda-beans/userguide.html) * The [Javadoc](https://www.joda.org/joda-beans/apidocs/index.html) * The change notes for the [releases](https://www.joda.org/joda-beans/changes-report.html) * The [related projects](related.html) including Maven, Gradle and IntelliJ integration ### Releases The 3.x branch is compatible with Java SE 21 or later. The 2.x branch is compatible with Java SE 8 or later. v3.x releases are mostly compatible with v2.x releases, see the [releases notes](https://www.joda.org/joda-beans/changes-report.html) for details. Deprecated methods have been removed. Joda-Beans depends on [Joda-Convert](https://www.joda.org/joda-convert/). There are a number of [optional dependencies](https://www.joda.org/joda-beans/dependencies.html) which help with integration. Available in the [Maven Central repository](https://search.maven.org/search?q=g:org.joda%20AND%20a:joda-beans&core=gav) For Java SE 6 compatibility, use [release 1.14](https://github.com/JodaOrg/joda-beans/releases/tag/v1.14). There are only [minor incompatibilities](https://www.joda.org/joda-beans/migration.html) with the 1.x codebase. ![Tidelift dependency check](https://tidelift.com/badges/github/JodaOrg/joda-beans) ### For enterprise Available as part of the Tidelift Subscription. Joda and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. If you want the flexibility of open source and the confidence of commercial-grade software, this is for you. [Learn more](https://tidelift.com/subscription/pkg/maven-org-joda-joda-beans?utm_source=maven-org-joda-joda-beans&utm_medium=github) ### Support Please use [Stack Overflow](https://stackoverflow.com/search?q=joda-beans) for general usage questions. GitHub [issues](https://github.com/JodaOrg/joda-beans/issues) and [pull requests](https://github.com/JodaOrg/joda-beans/pulls) should be used when you want to help advance the project. Any donations to support the project are accepted via [OpenCollective](https://opencollective.com/joda). To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. ### Release process * Update version (index.md, changes.xml) * Commit and push * `git push origin HEAD:refs/tags/release` * Code and Website will be built and released by GitHub Actions Release from local: * Ensure `gpg-agent` is running * `mvn clean release:clean release:prepare release:perform` ================================================ FILE: RELEASE-NOTES.txt ================================================ Joda-Beans ================================================ Joda-Beans is a library that provides full bean and property support for the JDK. The release runs on Java 21 or later. See https://www.joda.org/joda-beans/changes-report.html for changes Feedback -------- Feedback is best received using GitHub issues and Pull Requests. https://github.com/JodaOrg/joda-beans/ The Joda team ================================================ FILE: pom.xml ================================================ 4.0.0 org.joda joda-beans jar Joda-Beans 3.0.0-SNAPSHOT Beans and Properties, compatible with Java 21+ https://www.joda.org/joda-beans/ 2007 Apache License, Version 2.0 https://www.apache.org/licenses/LICENSE-2.0.txt repo Joda.org https://www.joda.org GitHub https://github.com/JodaOrg/joda-beans/issues/ scm:git:https://github.com/JodaOrg/joda-beans.git scm:git:https://github.com/JodaOrg/joda-beans.git https://github.com/JodaOrg/joda-beans HEAD jodastephen Stephen Colebourne Project Lead 0 https://github.com/jodastephen bcamel https://github.com/bcamel biteytech https://github.com/biteytech Hack Kampbjorn https://github.com/hackmann Chris Kent https://github.com/cjkent mediahype https://github.com/mediahype Will Nicholson https://github.com/wjnicholson Martynas Sateika https://github.com/martynassateika Andreas Schilling https://github.com/andreas-schilling troshanin https://github.com/troshanin Kevin Vella https://github.com/lega src/main/resources META-INF ${project.basedir} LICENSE.txt NOTICE.txt org.apache.maven.plugins maven-enforcer-plugin enforce-maven enforce 3.8.0 [21,) org.apache.maven.plugins maven-compiler-plugin default-testCompile --add-modules java.desktop --add-reads org.joda.beans=java.desktop org.apache.maven.plugins maven-surefire-plugin default-test true --add-modules java.desktop --add-reads org.joda.beans=java.desktop --add-exports org.joda.beans/org.joda.beans.sample=org.joda.convert test-without-modules test test false org.apache.maven.plugins maven-release-plugin -Doss.build -Doss.repo true v@{project.version} true org.kohsuke github-api ${github-api.version} org.apache.maven.plugins maven-assembly-plugin ${maven-assembly-plugin.version} org.apache.maven.plugins maven-checkstyle-plugin ${maven-checkstyle-plugin.version} org.apache.maven.plugins maven-changes-plugin ${maven-changes-plugin.version} org.apache.maven.plugins maven-clean-plugin ${maven-clean-plugin.version} org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} org.apache.maven.plugins maven-deploy-plugin ${maven-deploy-plugin.version} org.apache.maven.plugins maven-dependency-plugin ${maven-dependency-plugin.version} org.apache.maven.plugins maven-enforcer-plugin ${maven-enforcer-plugin.version} org.apache.maven.plugins maven-gpg-plugin ${maven-gpg-plugin.version} org.apache.maven.plugins maven-install-plugin ${maven-install-plugin.version} org.apache.maven.plugins maven-jar-plugin ${maven-jar-plugin.version} org.apache.maven.plugins maven-javadoc-plugin ${maven-javadoc-plugin.version} org.apache.maven.plugins maven-jxr-plugin ${maven-jxr-plugin.version} org.apache.maven.plugins maven-plugin-plugin ${maven-plugin-plugin.version} org.apache.maven.plugins maven-pmd-plugin ${maven-pmd-plugin.version} org.apache.maven.plugins maven-project-info-reports-plugin ${maven-project-info-reports-plugin.version} org.apache.maven.plugins maven-release-plugin ${maven-release-plugin.version} org.apache.maven.plugins maven-repository-plugin ${maven-repository-plugin.version} org.apache.maven.plugins maven-resources-plugin ${maven-resources-plugin.version} org.apache.maven.plugins maven-source-plugin ${maven-source-plugin.version} org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} org.apache.maven.plugins maven-surefire-report-plugin ${maven-surefire-report-plugin.version} org.apache.maven.plugins maven-toolchains-plugin ${maven-toolchains-plugin.version} org.jacoco jacoco-maven-plugin ${jacoco-maven-plugin.version} com.github.spotbugs spotbugs-maven-plugin ${spotbugs-maven-plugin.version} org.apache.maven.plugins maven-site-plugin ${maven-site-plugin.version} true attach-descriptor attach-descriptor en,de org.joda.external reflow-velocity-tools 1.2 org.joda joda-convert ${joda-convert.version} com.google.guava guava ${guava.version} true com.google.guava listenablefuture com.google.errorprone error_prone_annotations com.google.j2objc j2objc-annotations org.checkerframework checker-qual com.google.code.findbugs jsr305 org.joda joda-collect ${joda-collect.version} true org.junit.jupiter junit-jupiter ${junit.version} test org.assertj assertj-core ${assertj.version} test org.apache.maven.plugins maven-project-info-reports-plugin ${maven-project-info-reports-plugin.version} ci-management dependencies dependency-info issue-management licenses team scm summary org.apache.maven.plugins maven-checkstyle-plugin ${maven-checkstyle-plugin.version} false false false module-info.java org.apache.maven.plugins maven-javadoc-plugin ${maven-javadoc-plugin.version} javadoc 21 org.apache.maven.plugins maven-surefire-report-plugin ${maven-surefire-report-plugin.version} true org.apache.maven.plugins maven-changes-plugin ${maven-changes-plugin.version} changes-report org.apache.maven.plugins maven-pmd-plugin ${maven-pmd-plugin.version} 100 ${maven.compiler.release} module-info.java com.github.spotbugs spotbugs-maven-plugin ${spotbugs-maven-plugin.version} org.jacoco jacoco-maven-plugin ${jacoco-maven-plugin.version} report oss-build oss.build org.apache.felix maven-bundle-plugin ${maven-bundle-plugin.version} bundle-manifest process-classes manifest ${project.version} ${joda.osgi.packages} ${joda.osgi.require.capability} <_fixupmessages>"Classes found in the wrong directory"; restrict:=error; is:=ignore true org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF true true org.apache.maven.plugins maven-javadoc-plugin attach-javadocs package jar 21 org.apache.maven.plugins maven-source-plugin attach-sources package jar-no-fork org.apache.maven.plugins maven-checkstyle-plugin run-checkstyle process-sources checkstyle module-info.java com.puppycrawl.tools checkstyle ${checkstyle.version} org.jacoco jacoco-maven-plugin jacoco-initialize prepare-agent jacoco-site package report github-action env.GITHUB_ACTIONS true bc release-artifacts oss.repo org.apache.maven.plugins maven-assembly-plugin false src/main/assembly/dist.xml gnu make-assembly install single org.apache.maven.plugins maven-gpg-plugin sign-artifacts verify sign org.sonatype.central central-publishing-maven-plugin ${central-publishing-maven-plugin.version} true central-publish ${project.name} ${joda.publish.auto} ${joda.publish.wait} de.jutzig github-release-plugin ${github-release-plugin.version} Release v${project.version} See the [change notes](https://www.joda.org/joda-beans/changes-report.html#a${project.version}) for more information. v${project.version} true ${project.build.directory} joda-beans*-dist.tar.gz joda-beans*-dist.zip github-releases deploy release 3.27.3 33.4.8-jre 2.0.0 3.0.1 5.13.4 org.joda.beans.* osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=${maven.compiler.release}))" false validated 3.7.1 6.0.0 2.12.1 3.4.0 3.4.0 3.13.0 3.8.1 3.1.3 3.5.0 3.2.7 3.1.3 3.4.2 3.11.2 3.6.0 3.15.1 3.24.0 3.6.2 3.1.1 2.4 3.3.1 3.12.1 3.3.1 3.5.3 3.5.3 3.2.0 0.8.0 1.326 1.6.0 0.8.12 0.11.1 0.15.1 4.8.6.6 21 true false true none 10.23.1 src/main/checkstyle/checkstyle.xml false UTF-8 UTF-8 ================================================ FILE: src/changes/changes.xml ================================================ Changes Stephen Colebourne Major version based on Java SE 21. Mostly compatible with v2.x. Deprecated methods have been removed. Allow Java records to become beans. Add `RecordBean` interface that can be implemented by records. Add `LinkedByteArrayOutputStream`, which is like `ByteArrayOutputStream` but faster. Add `ResolvedType`, which allows generic type information to be managed in a simple way. Potentially incompatible change: Manual equals, hashCode and toString methods must now be located *before* the autogenerated block. This change allows nested classes to be written with their own equals, hashCode and toString methods, so long as the nested class is written *after* the autogenerated block. It is expected that most uses of Joda-Beans already have the equals, hashCode and toString methods before the autogenerated block and therefore will be unaffected. Add a new binary format. This change adds a third binary format, with a focus on size and performance. In testing it produces binary files similar or slightly smaller than the referencing binary format, but with faster serialization and deserialization. This solves a performance problem with the referencing format whereby it tried to deduplicate all beans, even those with very large hash codes. As part of this change, callers should now explicitly select which binary format they want using `JodaBeanBinFormat`. Potentially incompatible change: The standard and referencing binary formats now support null as a map key. Potentially incompatible change: The referencing binary format no longer deduplicates collections. The old format can still be parsed successfully. Potentially incompatible change: The standard binary and JSON formats now handle `Iterable` as a collection type. Incompatible change: The JSON serialization formats have changed for primitive arrays. Instead of a Joda-Convert formatted string, the array is output as a list of primitives. This also applies to multi-dimensional arrays. This is a much more natural JSON format. The old format can still be parsed successfully. Incompatible change: The JSON serialization formats have changed requiring fewer @meta and @type annotations. For example, where the type of the collection is Object, previously a String value was explicitly typed as a String, now the type is implicit. This is a much more natural JSON format. The old format can still be parsed successfully. Incompatible change: The simple JSON serialization format now uses a string instead of null for NaN for consistency. The new configuration 'JodaBeanJsonNumberFormat' can be used to control how NaN and Infinity are output. As part of this change, the extended literals from 'The JSON5 Data Interchange Format' can be used if desired. Potentially incompatible bug fix: Properties of type 'boolean[]' and 2-dimensional arrays are now cloned by default in immutable beans in line with existing behaviour. Cloning is opt-in for mutable beans using new settings on `PropertyDefinition`. Potentially incompatible bug fix: Binary and JSON parsers now accept the formats produced by v3.x. Certain edge cases now succeed when previously an exception would have been thrown. Fix code generation for property names that clash with code generated method parameters. Properties named `obj`, `other` or `propertyName` caused problems. These are now prefixed by `this` to avoid the clash. Fix `BeanAssert` to output the correct message. Previously there was no check for equals at the property level, nor were arrays properly converted to `String`. Fix code generation of light beans for `short`, `byte` and `char` fields. Allow deserialization to handle numbers greater than the capacity of an int. Add `PropertyPath` class, allowing multi-stage property lookups. New methods on MetaBean and MetaProperty to query an annotation, returning Optional. DirectBean annotation lookup now handles derived properties correctly. The jar file is now a multi-release jar file, with the module-info file moved. The classic jar file (without module-info.class) is no longer produced. Allow generics in metaImplements. Remove erroneous assertj dependency. Add 'metaImplements' bean definition option that allows meta beans to implement an interface. Allow IDEs to generate @Override tags without Joda-Beans removing them on regeneration. Switch master to main. Switch LGTM to CodeQL. Fix bug in referencing deserialization. Update dependencies. Avoid NPE in `MetaBeans`. Update Guava dependency. Add 'eol' command line argument to control the end-of-line character. Ensure meta-bean only registered once. Provide ability to copy a bean to a builder of a different type. See JodaBeanUtils.copy(Bean, Class). Add MetaBeanProvider annotation for more flexible meta-bean lookup. Fix mutable beans where the subclass has no properties. Fixes #210, #221. Fix binary serialization of Joda-Convert types with intermediate interfaces in referencing format. Fix toString() to include derived properties. Handle repeated annotations more cleanly. Call JodaBeansUtils.toString() on all properties, not just the last. Fix manual builders when used with minimal style. Add smart reader, that dynamically works out the format of the input. Provide the ability to manually write a builder. New command line flag -generated to add @Generated annotation. Fixes #209, #149 Change XML parsing to share factory. The JDK bug was fixed many years ago now, please use JDK 8u20 or later to avoid issues. Fix referencing binary format for serialized nulls. Fix referencing binary format for serialized nulls. Fix referencing binary format for interfaces serialized via Joda-Convert. Update Joda-Convert version. Add referencing binary format that typically uses less space. Ensure that annotations are parsed correctly on fields. Ensure that all annotations are available at runtime. Ensure that builders on mutable beans are handled correctly. Create `toBuilder()` methods and fix case where empty parent bean didn't compile. Fix handling of deprecated properties. Ensure that Javadoc tag is not output twice. Move the tag to be output last, after other tags. Add ability to serialize XML to an `Appendable`. Deprecate existing `writeToBuffer()` methods. See #196. Add Tidelift commercial support and security policy. Allow deserializers to be registered in config files. Avoid NullPointerException in finally block. Parse class headers spread over multiple lines. Fixes #191. Update Guava and Joda-Collect versions. Allow primitive integral types to be deserialized into floating point properties. Fixes #190. Ensure tests and functionality work correctly on Java 9. Fix light and minimal beans to respect aliases. Aliases are useful for handling the rename of properties. Fixes #187. Add classic jar file for those that can't handle module-info.class. Fixes #188. Remove integration projects - Freemarker, Kryo, Mongo. These are now available as separate Maven artifacts, see https://github.com/JodaOrg/joda-beans-integrate. Add module-info for Java 9. Fixes #180. Allow serialization of derived properties. Use JodaBeanSer::withIncludeDerived(true). Fixes #183. Change serialization format of simple JSON. Primitive arrays are now output in standard JSON format, not as a string. Any byte arrays are still output as base-64. Simple map format was also changed to retain the arrays. Fixes #186. Handle double space in field definitions. Fixes #182. Handle wildcards better when looking up generic types. Fixes #185. Avoid NPE when parsing JSON. If the generic type of the key could not be decoded, NPE could result. Fixes #184. Fix error message for table/grid. Fixes #179. Fix serialization issues for collections. ImmutableSortedMap now works. Collections where the generic is `Comparable` now work. Update and redesign build to support Java 9. Fix cached hash code to be transient. It must not be serialized. Fixes #177. Fix minimal and light beans. Code erroneously assumed reflection returns fields in source code order. Fixes #176. Ensure that properties stay in order. Use LinkedHashMap instead of HashMap where necessary. Move to Java 8. Change light beans from reflection to method handles. Change minimal beans to not have generated meta-bean class and disallow subclasses. Fixes #155. Use diamond operators in generated code. Fixes #5. Add @SafeVarargs annotation. Fixes #156. Change BeanBuilder.get to use meta property type. Fixes #152. Remove comments for Clover ON/OFF. Use the AUTOGENERATED START/END comments instead. Fixes #157. MetaBean must pass type of bean to builder. This is needed when the meta-bean is not generated. Fixes #158. Ensure light beans default empty collections. Fixes #148. Remove deprecated methods. Additional meta-bean methods - isBuildable(), of(Class), annotations(), annotation(Class). Fixes #161. Register meta-beans via MetaBean.register(). Deprecate old way on JodaBeanUtils. Fixes #166. Add methods to assist with test coverage. Force coverage of Joda-Beans branches so the coverage percentage is more meaningful. Add `Automatic-Module-Name` into `MANIFEST.MF`. Locks in module name for Java SE 9. Fixes #175. Generate property change as `final transient`. Fixes #173. Handle multi-line annotations after `@PropertyDefinition`. This simply looks for a comma at the end of the previous line, which isn't perfect but better than nothing. Fixes #174. Add lenient mode for deserialization, see `SerDeserializers`. This allows unknown properties and some invalid types to be ignored. Fixes #170. Support derived properties on light and minimal beans. Fixes #169. Avoid warnings with generated code setString() and setAll(). Fixes #168. Add notBlank validation. Fixes #167. Ensure builder calls super constructor in hierarchy. Fixes #150. Rename config file from "jdk6" to "jdk". Fixes #163. ToString style of 'omit' did not affect builder. Fixes #164. Serialize to/from a Map of Maps. Fixes #159. Deprecate PropertyMap, use JodaBeanUtils.flatten(bean) or BasicPropertyMap.of(bean). Deprecate BeanQuery, use functional interfaces in Java SE 8. Deprecate BeanBuilder methods - setString() and setAll(). Redesign reflective meta-bean. Fixes #160. JSON/binary serialization fails to read in a double[][] written with meta type. Fixes #147. Allow mutable light beans to control constructor scope. Fixes #145. Generated factory methods do not have Javadoc @return. Fixes #146. Ensure light bean builder handles arbitrary meta property implementations. Fixes #144. Avoid generating methods that have no advantage in private builders. Fixes #143. Light bean setters fail to work via bean abstraction. Fixes #142. Light meta bean field should be final. Fixes #141. Scope of meta bean and builder should match scope of main bean. Fixes #140. Add deserializer providers, to allow more extensibility in deserialization. Fixes #128. Extend concept of "light" beans to mutable. Light beans generate minimal code - no meta bean or builder. Fixes #139. Avoid NPE for mutable beans with builder. Fixes #138. Allow clone methods on immutable beans. Allow clone methods to be skipped during generation. Fixes #135. Enhance Guava deserialization when using certain immutable collection types. Fixes #131. Incorrect config file for JDK 6. Fixes #134. Provide integration with Kryo serialization. Fixes #130. Add generation of static factory method. Fixes #123. Allow scope of meta-bean to be controlled. Fixes #127. Optional properties on light beans did not report the correct property type. This caused serialization to fail. Also fix field-based access problems due to lack of setAccessible. Fixes #126. Handle JSON parsing where integer can be converted safely to double or float. Fixes #122. Add support for EnumSet. Fixes #125. Change equals/hashCode/toString to use fields, not getters, for immutable beans. Allow equals/hashCode/toString to be controlled , including selectively omitted. Fixes #118, #121. Provide ability to generate ConstructorProperties annotation. Fixes #120. Allow tolerance to be set when comparing beans using BeanAssert. Additional methods on JodaBeanUtils provides tools for manual equals() methods. Fixes #117. Make bean parser more lenient. Handle open brace immediately following Bean or ImmutableBean in an implements clause. Fixes #116. Use configured prefix for cachedHashCode and propertyChangeSupport. Fixes #115. Avoid null check in array clone getters where possible. Fixes #114. Fix light-weight immutable bean generation. Generation needs to add call to register the meta-bean. Constructor location logic is now more lenient to handle interface/class separation. Fixes #111. Fix XML to read/write interface base keys. Handle case where interface does note extend Bean interface. Fixes #119. Add light-weight immutable bean generation. Light-weight code generation using reflection to implement the bean methods. No Meta class or Builder is generated. Fixes #111. Add basic support for bound properties. Implementation only handles non-final properties on mutable beans. Fixes #78. Support package, protected and public scoped immutable constructors. Fixes #107. Support package-scoped builder classes. Fixes #109. Support package-scoped getters/setters. Fixes #108. Allow immutable builder property type to be manually controlled. Fixes #103. Enhance generation of varargs builder methods. Support "List<? extends Foo>" and "List<?>" Fixes #104. Generate documentation for builder methods based on user-written docs. Fixes #106. Fix code generation for immutable beans where there are two generic types and the types are linked. For example, Foo<A, B extends Comparable<A>>. Fixes #110. Enable better test coverage. Fixes #102. Optimise JodaBeanUtils for hotspot inlining. Fixes #101. Optimise internals of generated builders to use immutable collections. This avoids unnecessary copying and object creation. Fixes #96. Provide details of files changed by code generation. This allows tooling, such as the maven plugin, to be enhanced. Fixes #99. Standard format for exceptions in code generation. Dedicated exception type allows tooling, such as the maven plugin, to be enhanced. Fixes #98. Add related projects page to website. Fixed parsing of verbose command line flag. Fixes #97. Add ImmutablePreBuild annotation. This handles the case where a property needs to be defaulted from the value of another property. In most cases, ImmutableDefaults and/or ImmutableValidator are sufficient. Fixes #95. Generate serialization version id. If the class implements Serializable and there is no manual serialVersionUID, then one will be generated. Fixes #94. Support Optional properties in serialization. If an optional property is used, support it in serialization. This works for everything except collection types. Fixes #93. Support Optional return type for getters of nullable properties. Allows the instance variable of a property to remain nullable (as recommended for Java 8) but with the getter returning an Optional wrapper. Simply declare the PropertyDefinition with 'get="optional"'. Fixes #92. Avoid including derived properties in equals/hashCode. Fixes #91. Add support for protected scope getters and setters. Fixes #90. Fix bean generation to handle a lack of spaces in field initializers. Fixes #87. Fix bean generation to handle a property of a wildcard list type. While the need for this is rare, better processing is needed. The fix requires use of the PropertyDefinition "type" attribute in certain cases. Fixes #88. The generated hash codes had a flaw and the algorithm has been changed. Previously, they used (h += h * 31 + value.hashCode). Now, they use (h = h * 31 + value.hashCode). The incorrect version failed to generate unique hash codes when a bean mostly contained null properties. This causes all beans to regenerate. Fixes #89. Add varargs overrides for collections in immutable builders. Fixes #85. Fix code generation of immutable package-scoped beans. Fixes #86. Add ability to iterate over all the beans within a bean. Depth-first iteration handling collections. Fixes #84. Fix parsing of class name with extends clause union types. Generic parameters on second and subsequent union types are not supported. Fixes #83. Add alias support to PropertyDefinition. A simple mechanism to handle property renames. Fixes #82. Fix parsing of class name with extends clause generics of type with two generic parameters. Fixes #81. Add option to allow property values to be defaulted on immutable beans. New annotation @ImmutableDefaults allows default values to be set. Fixes #80. Add option to allow hash codes to be cached. New attribute on @BeanDefinition allows caching of hash codes. Fixes #79. Reduce scope of serialization helper classes. MsgPack, MsgPackInput, MsgPackOutput and JodaBeanXml. Backwards incompatible, but should not have been used. Add JSON round-trip serialization. Fixes #75. Use effective type exposed by Joda-Convert. Joda-Convert v1.7 exposes the effective type of the converted string. This can be more useful to use in serialization than the value type. For example, where a public interface has the `FromString` annotation and non-public subclass has the `ToString`. Fixes #76. Better documentation. Fixes #74. Fix to add @Override annotation on toBuilder(). Fixes #73. Fix serialization to handle subclasses of enums. Fixes #72. Fix immutable beans with private builders. Meta-Bean builder() method returned the private buidler. Fixes #70. Fix immutable builder setString() method to actually convert from a string. Fixes #69. Add JodaBeansUtils.notEmpty(Collection) and JodaBeansUtils.notEmpty(Map). Fixes #71. Update docs for v1.0. Provide @ImmutableValidator to allow immutable constructors to be manually validated. Fixes #65. Generate Javadoc param tags for generic types in meta/builder. Fixes #68. Add getter/setter style of "field". As all access is direct to the field, a weird getter/setter can be used. Fixes #67. Remove Bean.clone(). Clashes with generic union types. Immutable beans no longer generate a clone method. Use JodaBeanUtils.clone(bean) instead. Fixes #66. Block immutable beans from using EnumBiMap, EnumHashBiMap, HashBiMap, EnumMultiset, HashMultiset, LinkedHashMultiset, TreeMultiset, ArrayListMultimap, LinkedListMultimap, HashMultimap, LinkedHashMultimap, TreeMultimap, SortedSetMultimap SparseGrid, DenseGrid. Change Multimap interface to use ArrayListMultimap, not HashMultimap, because ImmutableMultimap is list based. Fixes #64. Enable selective use of Override annotation. Fixes #63. Undo deprecation of BasicImmutableBeanBuilder. Fix immutable beans builder method comment. Fixes #62. Enhance and fix 2D array support in serialization. Fixes #61. Enhance and fix meta-type support in serialization. Fixes #60. Add support for Joda-Collect Grid interface. Fixes #59. Add support for Guava BiMap interface. Fixes #58. Handle collections in clone(). Fixes #55. Do not clone in getters of mutable beans for arrays and java.util.Date. Fixes #57. Add mime types for serialized formats. Fixes #56. Add support for Guava Table interface. Fixes #54. Immutable subclass builders do not work. Immutable and builder-based beans will regenerate. Fixes #53. Bean builder should have getters. Immutable and builder-based beans will regenerate. Fixes #52. Deprecate BasicImmutableBeanBuilder. Support three generic parameters. Fixes #51. More secure XML parsing. Add Joda-Bean binary serialization based on MessagePack. Fixes #49. More flexible XML parsing wrt Joda-Convert. Handle a bean that has Joda-Convert annotations added, or vice versa. Fixes #50. Invalid code generated for an abstract @ImmutableBean. Fixes #48. Guava MultiSet serialized incorrectly. Was serializing using the set size, not the unique elements size. Fixes #47. Choose known types in serialization carefully. Reduce the set from v0.9.2 as that set of types was too large. Fixes #46. Fix BeanComparisonError. Fixes #45. Remove encodeClass/decodeClass from main serialization API. Fixes #44. Handle refactored beans in deserialization. Fixes #43. BasicBeanBuilder get(String) returns builder rather than the requested data. Backwards incompatible, but the old code is useless so will never have been used. Fixes #42. Ensure XML reader property closed. Fixes #41. Handle type renames in deserialization. Fixes #40. Short types flag not being used in JodaBeanSer. Fixes #39. Fix immutable collection copies to preserve comparators. Affects SortedSet and SortedMap. Fixes #37. Remove incorrect suppress unchecked in immutable generic beans. Fixes #38. Support partially final beans and immutable subclasses. This support is complex and not recommended, but sometimes necessary. Fixes #24. Recreate XMLInputFactory each time due to JDK bug JDK-8028111. Fixes #36. Fix to ensure nested class constructors are private if the type is final. May cause beans to regenerate. Fixes #35. Extend notNull validation to collection properties. May cause beans to regenerate. Fixes #34. Enhance PropertyStyle. Add isReadOnly(). Fixes #33. Add 'equalIgnoring' utility to compare two beans ignoring one or more properties. Fixes #32. XML generation of beans with no fields broken. Affected COMPACT mode, not PRETTY mode. Fixes #30. FlexiMap should retain the order of properties. Use LinkedHashMap not HashMap. Fixes #31. Fix code generation unchecked annotation when no writable properties. Allow beans to have two generic type parameters. Fixes #21. Fix code generation of private immutable builders. Fixes #26. Parse trailing comments on property definitions. Fixes #27. Add setting to allow immutable builders to be private. Fixes #26. Avoid code generating two lines next to one another. Handle extra spaces in class/extends definitions. Fixes #25. Fix code generation for properties of generic type array. Where bean is Foo<T> and property is T[]. Also where immutable bean and property is T. Fixes #22. Bean toString should process arrays correctly. Fixes #23. Enhance handling of non-null and non-empty fields especially in immutable beans. See #20. Immutable beans should handle nullable fields. Fixes #20. Generate an immutable bean with no properties correctly. Handle classes that are loaded but not initialized. Fixes #19. Fix XML parsing of complex map entries. Handle multi-line class definition. Fixes #17. Fix FlexiBean serialization. Fixes #18. SerIteratorFactory off by one bug. XML format no longer encodes tabs and newlines in elements. Allow private getters/setters using PropertyDefinition. Rename XML format map items to 'entry'. Allow map keys to be beans, using two 'item' elements beneath 'entry'. Extend analysis of collection/map generic types. Allow short types to be switched off. Handle simple types better when defined by unknown interface. Generate correct Javadoc for builder static method with generics. Allow known types to be built up during serialization. Permit XML format to omit root type. Output Joda-Convert data whenever available. Move to OSGi generation via Maven plugin. Add XML round-trip serialization. Fixes #16. Allows the bean to be converted to and from XML in a human readable format. Enhance FlexiBean and MapBean. Fixes #15. These now work more like the original intention. Properties are always created on demand. FlexiBean property names are now validated to a minimal format. Identify Derived and Immutable properties at runtime. Fixes #14. Rename readWrite() to style() and PropertyReadWrite to ProperyStyle. Some existing beans may regenerate. Generate final classes for final beans. Fixes #13. Some existing beans may regenerate. Parse annotations above @PropertyDefinition as well as those below. Fixes #10. Some existing beans may regenerate. Add support for clone on beans.. Fixes #12. All existing beans will regenerate. Add support for immutable beans. Fixes #11. All existing beans will regenerate. Move location of equals/hashCode/toString methods in generation. All existing beans will regenerate. Allow generated beans to implement interface, rather than extend class. Fixes #9. Move propertyGet/propertySet/validate into meta-bean All existing beans will regenerate. Generate toString() methods. Fixes #8. All existing beans will regenerate. Optimize performance of generated equals for primitive numbers. Some existing beans will regenerate. Home page at GitHub. Adjust code generation so can reformat in Eclipse without changing generated code. Existing beans will regenerate, even though the only change is one blank line. Add checkstyle Change to use m2e Maven Eclipse Fix indentation issue in metaPropertyMap field. Existing beans will regenerate, even though the only change is indentation. Refactor BeanCodeGen to allow it to be used from tools. Fix command line arguments - -v -> -verbose. Add getString() and setString() overrides that take a StringConvert instance. Add metaXxx(Class) method to work around Eclipse/javac/Intellij generics compiler issues. Existing beans will need regenerating. Allow derived property to be abstract or final. Set correct read/write flag for final fields. Make generics more correct. Add builder methods based on meta-property. Move example code to correct location. Allow a property to be named 'map'. Handle empty comments correctly. Extend builder to support setting by string. Update to Joda-Convert v1.2 and use new feature to improve string conversion. DirectBean no longer extends BasicBean to simplify the hierarchy. Add BeanQuery and comparator support. Handle generic subclasses better in JodaBeanUtils collection/map type extraction. Handle arrays in JodaBeanUtils equals method. Fix JodaBeanUtils to handle collections and sets as well as lists. Fix generation of non-collection final properties. Add JodaBeanUtils.clone(). Add JodaBeanUtils.metaBean(), to lookup meta-bean by class. This requires regeneration of direct beans. Improve generation of imports. This may require regeneration of direct beans. Handle write-only properties better. This requires regeneration of direct beans. Allow conversion to and from a standard format string from meta-property. Add basic validation support. Add derived property annotation and support. Add BeanBuilder concept. Refactor to improve equals/hashCode performance. Fix property/meta-property equals/hashCode. Enhance meta-property map. Minor fixes. Handle generic subclass of a generic class. Handle subclass of a generic class. Initial version. ================================================ FILE: src/main/assembly/dist.xml ================================================ dist tar.gz zip ${artifactId}-${version} checkstyle.xml LICENSE.txt NOTICE.txt pom.xml RELEASE-NOTES.txt src target *.jar ================================================ FILE: src/main/checkstyle/checkstyle.xml ================================================ ================================================ FILE: src/main/java/module-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Joda-Beans is a small framework that adds properties to Java, greatly enhancing JavaBeans. *

* The key concept is to allow each property on a bean to be accessed as an object in its own right. * This provides the hook for other technologies to build on, such as serialization, mapping, * expression languages and validation. */ module org.joda.beans { // dependency on Joda-Convert requires transitive org.joda.convert; // dependency on XML parser requires java.xml; // optional dependency on Guava requires static com.google.common; // optional dependency on Joda-Collect requires static org.joda.collect; // export all packages exports org.joda.beans; exports org.joda.beans.gen; exports org.joda.beans.impl; exports org.joda.beans.impl.direct; exports org.joda.beans.impl.flexi; exports org.joda.beans.impl.light; exports org.joda.beans.impl.map; exports org.joda.beans.impl.reflection; exports org.joda.beans.ser; exports org.joda.beans.ser.bin; exports org.joda.beans.ser.json; exports org.joda.beans.ser.map; exports org.joda.beans.ser.xml; exports org.joda.beans.test; } ================================================ FILE: src/main/java/org/joda/beans/Bean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.util.NoSuchElementException; import java.util.Set; /** * A bean consisting of a set of properties. *

* The implementation may be any class, but is typically a standard JavaBean * with get/set methods. Alternate implementations might store the properties * in another data structure such as a map. */ public interface Bean { /** * Gets the meta-bean representing the parts of the bean that are * common across all instances, such as the set of meta-properties. *

* The meta-bean can be thought of as the equivalent of {@link Class} but for beans. * * @return the meta-bean, not null */ public abstract MetaBean metaBean(); /** * Gets a property by name. *

* Each bean consists of a known set of properties. * This method checks whether there is a property with the specified name. *

* The base interface throws an exception if the name is not recognised. * By contrast, the {@code DynamicBean} interface creates the property on demand. * * @param the property type, optional, enabling auto-casting * @param propertyName the property name to retrieve, not null * @return the property, not null * @throws NoSuchElementException if the property name is invalid */ public default Property property(String propertyName) { return metaBean().metaProperty(propertyName).createProperty(this); } /** * Gets the set of property names. *

* Each bean consists of a known set of properties. * This method returns the known property names. * * @return the unmodifiable set of property names, not null */ public default Set propertyNames() { return metaBean().metaPropertyMap().keySet(); } } ================================================ FILE: src/main/java/org/joda/beans/BeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A builder for a bean, providing a safe way to create it. *

* This interface allows a bean to be created even if it is immutable. * * @param the type of the bean */ public interface BeanBuilder { /** * Gets the value of a single property previously added to the builder. * * @param propertyName the property name to query, not null * @return the previously set value, null if none * @throws RuntimeException thrown if the property name is invalid */ public abstract Object get(String propertyName); /** * Gets the value of a single property previously added to the builder. * * @param metaProperty the meta-property to query, not null * @return the previously set value, null if none * @throws RuntimeException thrown if the property is invalid * @param

the type of the property. */ public abstract

P get(MetaProperty

metaProperty); /** * Sets the value of a single property into the builder. *

* This will normally behave as per a {@code Map}, however it may not * and as a general rule callers should only set each property once. * * @param propertyName the property name to set, not null * @param value the property value, may be null * @return {@code this}, for chaining, not null * @throws RuntimeException optionally thrown if the property name is invalid */ public abstract BeanBuilder set(String propertyName, Object value); /** * Sets the value of a single property into the builder. *

* This will normally behave as per a {@code Map}, however it may not * and as a general rule callers should only set each property once. * * @param metaProperty the meta-property to set, not null * @param value the property value, may be null * @return {@code this}, for chaining, not null * @throws RuntimeException optionally thrown if the property is invalid */ public abstract BeanBuilder set(MetaProperty metaProperty, Object value); /** * Builds the bean from the state of the builder. *

* Once this method has been called, the builder is in an invalid state. * The effect of further method calls is undetermined. * * @return the created bean, not null */ public abstract T build(); } ================================================ FILE: src/main/java/org/joda/beans/BeanIterator.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import org.joda.beans.ser.SerIteratorFactory; /** * An iterator over beans. */ final class BeanIterator implements Iterator { /** * The stack of beans. */ private final List stack = new ArrayList<>(32); /** * Creates an instance. * * @param root the bean to iterate over */ BeanIterator(Bean root) { this.stack.add(root); } @Override public boolean hasNext() { return !stack.isEmpty(); } @Override public Bean next() { if (!hasNext()) { throw new NoSuchElementException("No more elements in the iterator"); } // next bean to return is head of the stack var currentBean = stack.remove(stack.size() - 1); // temp used to reverse the order of child beans to match depth-first order // alternative is to insert into stack at a fixed index (lots of array copying) var temp = new ArrayDeque(32); for (var mp : currentBean.metaBean().metaPropertyIterable()) { findChildBeans(mp.get(currentBean), mp, currentBean.getClass(), temp); } stack.addAll(temp); return currentBean; } // find child beans, including those in collections private void findChildBeans(Object obj, MetaProperty mp, Class beanClass, Deque temp) { if (obj != null) { if (obj instanceof Bean bean) { temp.addFirst(bean); } else { var it = SerIteratorFactory.INSTANCE.create(obj, mp, beanClass); if (it != null) { while (it.hasNext()) { it.next(); findChildBeans(it.key(), mp, Object.class, temp); findChildBeans(it.value(), mp, Object.class, temp); findChildBeans(it.column(), mp, Object.class, temp); } } } } } @Override public void remove() { throw new UnsupportedOperationException("BeanIterator does not support remove()"); } } ================================================ FILE: src/main/java/org/joda/beans/DynamicBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A dynamic bean that allows properties to be added and removed. *

* A JavaBean is defined at compile-time and cannot have additional properties added. * Instances of this interface allow additional properties to be added and removed * probably by wrapping a map */ public interface DynamicBean extends Bean { /** * Gets the meta-bean representing the parts of the bean that are * common across all instances, such as the set of meta-properties. * * @return the meta-bean, not null */ @Override public abstract DynamicMetaBean metaBean(); /** * Gets a property by name. *

* This will not throw an exception if the property name does not exist. * Whether a property is immediately created or not is implementation dependent. * * @param the property type, optional, enabling auto-casting * @param propertyName the property name to retrieve, not null * @return the property, not null */ @Override public abstract Property property(String propertyName); /** * Adds a property to those allowed to be stored in the bean. *

* Some implementations will automatically add properties, in which case this * method will have no effect. * * @param propertyName the property name to check, not empty, not null * @param propertyType the property type, not null */ public abstract void propertyDefine(String propertyName, Class propertyType); /** * Removes a property by name. * * @param propertyName the property name to remove, null ignored */ public abstract void propertyRemove(String propertyName); } ================================================ FILE: src/main/java/org/joda/beans/DynamicMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A dynamic meta-bean which works with {@code DynamicBean}. *

* A dynamic bean can have properties added or removed at any time. * As such, there is a different meta-bean for each dynamic bean. * The meta-bean allows meta-properties to be created on demand. */ public interface DynamicMetaBean extends MetaBean { /** * Creates a bean builder that can be used to create an instance of this bean. *

* All properties added to the builder will be created and appear in the result. * * @return the bean builder, not null * @throws UnsupportedOperationException if the bean cannot be created */ @Override public abstract BeanBuilder builder(); /** * Get the type of the bean represented as a {@code Class}. * * @return the type of the bean, not null */ @Override public abstract Class beanType(); /** * Gets a meta-property by name. *

* This will not throw an exception if the meta-property name does not exist. * Whether a meta-property is immediately created or not is implementation dependent. * * @param the property type, optional, enabling auto-casting * @param propertyName the property name to retrieve, not null * @return the meta property, not null */ @Override public abstract MetaProperty metaProperty(String propertyName); //----------------------------------------------------------------------- /** * Defines a property for the bean. *

* Some implementations will automatically add properties, in which case this * method will have no effect. * * @param propertyName the property name to check, not empty, not null * @param propertyType the property type, not null */ public abstract void metaPropertyDefine(String propertyName, Class propertyType); /** * Removes a property by name. * * @param propertyName the property name to remove, null ignored */ public abstract void metaPropertyRemove(String propertyName); } ================================================ FILE: src/main/java/org/joda/beans/ImmutableBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * An immutable bean consisting of a set of properties. *

* This marker interface allows immutable beans to be identified. */ public interface ImmutableBean extends Bean { } ================================================ FILE: src/main/java/org/joda/beans/JodaBeanUtils.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.function.Function; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.collect.grid.DenseGrid; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableGrid; import org.joda.collect.grid.SparseGrid; import org.joda.convert.StringConvert; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.BiMap; import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableTable; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultiset; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.SetMultimap; import com.google.common.collect.SortedMultiset; import com.google.common.collect.Table; import com.google.common.collect.TreeMultiset; /** * A set of utilities to assist when working with beans and properties. */ public final class JodaBeanUtils { /** * The cache of meta-beans. */ private static final StringConvert converter = new StringConvert(); /** * Restricted constructor. */ private JodaBeanUtils() { } //----------------------------------------------------------------------- /** * Gets the standard string format converter. *

* This returns a singleton that may be mutated (holds a concurrent map). * New conversions should be registered at program startup. * * @return the standard string converter, not null */ public static StringConvert stringConverter() { return converter; } //----------------------------------------------------------------------- /** * Checks if two objects are equal handling null. * * @param obj1 the first object, may be null * @param obj2 the second object, may be null * @return true if equal */ public static boolean equal(Object obj1, Object obj2) { if (obj1 == obj2) { return true; } if (obj1 == null || obj2 == null) { return false; } if (obj1.getClass().isArray()) { return equalsArray(obj1, obj2); } // this does not handle arrays embedded in objects, such as in lists/maps, // but you shouldn't use arrays like that, should you? return obj1.equals(obj2); } // extracted from equal(Object,Object) to aid hotspot inlining private static boolean equalsArray(Object obj1, Object obj2) { if (obj1.getClass() != obj2.getClass()) { return false; } return switch (obj1) { case Object[] objects -> Arrays.deepEquals(objects, (Object[]) obj2); case int[] ints -> Arrays.equals(ints, (int[]) obj2); case long[] longs -> Arrays.equals(longs, (long[]) obj2); case byte[] bytes -> Arrays.equals(bytes, (byte[]) obj2); case double[] doubles -> Arrays.equals(doubles, (double[]) obj2); case float[] floats -> Arrays.equals(floats, (float[]) obj2); case char[] chars -> Arrays.equals(chars, (char[]) obj2); case short[] shorts -> Arrays.equals(shorts, (short[]) obj2); case boolean[] booleans -> Arrays.equals(booleans, (boolean[]) obj2); default -> false; // unreachable? }; } /** * Checks if two floats are equal based on identity. *

* This performs the same check as {@link Float#equals(Object)}. * * @param val1 the first value, may be null * @param val2 the second value, may be null * @return true if equal */ public static boolean equal(float val1, float val2) { return Float.floatToIntBits(val1) == Float.floatToIntBits(val2); } /** * Checks if two floats are equal within the specified tolerance. *

* Two NaN values are equal. Positive and negative infinity are only equal with themselves. * Otherwise, the difference between the values is compared to the tolerance. * * @param val1 the first value, may be null * @param val2 the second value, may be null * @param tolerance the tolerance used to compare equal * @return true if equal */ public static boolean equalWithTolerance(float val1, float val2, double tolerance) { return (Float.floatToIntBits(val1) == Float.floatToIntBits(val2)) || Math.abs(val1 - val2) <= tolerance; } /** * Checks if two doubles are equal based on identity. *

* This performs the same check as {@link Double#equals(Object)}. * * @param val1 the first value, may be null * @param val2 the second value, may be null * @return true if equal */ public static boolean equal(double val1, double val2) { return Double.doubleToLongBits(val1) == Double.doubleToLongBits(val2); } /** * Checks if two doubles are equal within the specified tolerance. *

* Two NaN values are equal. Positive and negative infinity are only equal with themselves. * Otherwise, the difference between the values is compared to the tolerance. * The tolerance is expected to be a finite value, not NaN or infinity. * * @param val1 the first value, may be null * @param val2 the second value, may be null * @param tolerance the tolerance used to compare equal * @return true if equal */ public static boolean equalWithTolerance(double val1, double val2, double tolerance) { return (Double.doubleToLongBits(val1) == Double.doubleToLongBits(val2)) || Math.abs(val1 - val2) <= tolerance; } /** * Returns a hash code for an object handling null. * * @param obj the object, may be null * @return the hash code */ public static int hashCode(Object obj) { if (obj == null) { return 0; } if (obj.getClass().isArray()) { return hashCodeArray(obj); } return obj.hashCode(); } // extracted from hashCode(Object) to aid hotspot inlining private static int hashCodeArray(Object obj) { return switch (obj) { case Object[] objects -> Arrays.deepHashCode(objects); case int[] ints -> Arrays.hashCode(ints); case long[] longs -> Arrays.hashCode(longs); case byte[] bytes -> Arrays.hashCode(bytes); case double[] doubles -> Arrays.hashCode(doubles); case float[] floats -> Arrays.hashCode(floats); case char[] chars -> Arrays.hashCode(chars); case short[] shorts -> Arrays.hashCode(shorts); case boolean[] booleans -> Arrays.hashCode(booleans); default -> obj.hashCode(); // unreachable? }; } /** * Returns a hash code for a {@code boolean}. * * @param value the value to convert to a hash code * @return the hash code */ public static int hashCode(boolean value) { return value ? 1231 : 1237; } /** * Returns a hash code for an {@code int}. * * @param value the value to convert to a hash code * @return the hash code */ public static int hashCode(int value) { return value; } /** * Returns a hash code for a {@code long}. * * @param value the value to convert to a hash code * @return the hash code */ public static int hashCode(long value) { return Long.hashCode(value); } /** * Returns a hash code for a {@code float}. * * @param value the value to convert to a hash code * @return the hash code */ public static int hashCode(float value) { return Float.hashCode(value); } /** * Returns a hash code for a {@code double}. * * @param value the value to convert to a hash code * @return the hash code */ public static int hashCode(double value) { return Double.hashCode(value); } //----------------------------------------------------------------------- /** * Returns the {@code toString} value handling arrays. * * @param obj the object, may be null * @return the string, not null */ public static String toString(Object obj) { if (obj == null) { return "null"; } if (obj.getClass().isArray()) { return toStringArray(obj); } return obj.toString(); } // extracted from toString(Object) to aid hotspot inlining private static String toStringArray(Object obj) { return switch (obj) { case Object[] objects -> Arrays.deepToString(objects); case int[] ints -> Arrays.toString(ints); case long[] longs -> Arrays.toString(longs); case byte[] bytes -> Arrays.toString(bytes); case double[] doubles -> Arrays.toString(doubles); case float[] floats -> Arrays.toString(floats); case char[] chars -> Arrays.toString(chars); case short[] shorts -> Arrays.toString(shorts); case boolean[] booleans -> Arrays.toString(booleans); default -> obj.toString(); // unreachable? }; } //----------------------------------------------------------------------- /** * Checks if the two beans have the same set of properties. *

* This comparison checks that both beans have the same set of property names * and that the value of each property name is also equal. * It does not check the bean type, thus a {@link FlexiBean} may be equal * to a {@link DirectBean}. *

* This comparison is usable with the {@link #propertiesHashCode} method. * The result is the same as that if each bean was converted to a {@code Map} * from name to value. * * @param bean1 the first bean to compare, not null * @param bean2 the second bean to compare, not null * @return true if equal */ public static boolean propertiesEqual(Bean bean1, Bean bean2) { var names = bean1.propertyNames(); if (!names.equals(bean2.propertyNames())) { return false; } for (var name : names) { var value1 = bean1.property(name).get(); var value2 = bean2.property(name).get(); if (!equal(value1, value2)) { return false; } } return true; } /** * Returns a hash code based on the set of properties on a bean. *

* This hash code is usable with the {@link #propertiesEqual} method. * The result is the same as that if each bean was converted to a {@code Map} * from name to value. * * @param bean the bean to generate a hash code for, not null * @return the hash code */ public static int propertiesHashCode(Bean bean) { var hash = 7; var names = bean.propertyNames(); for (var name : names) { var value = bean.property(name).get(); hash += hashCode(value); } return hash; } /** * Returns a string describing the set of properties on a bean. *

* The result is the same as that if the bean was converted to a {@code Map} * from name to value. * * @param bean the bean to generate a string for, not null * @param prefix the prefix to use, null ignored * @return the string form of the bean, not null */ public static String propertiesToString(Bean bean, String prefix) { if (prefix == null) { return propertiesToString(bean, ""); } var names = bean.propertyNames(); var buf = new StringBuilder((names.size()) * 32 + prefix.length()).append(prefix); buf.append('{'); if (!names.isEmpty()) { for (var name : names) { var value = bean.property(name).get(); buf.append(name).append('=').append(value).append(',').append(' '); } buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } /** * Flattens a bean to a {@code Map}. *

* The returned map will contain all the properties from the bean with their actual values. * * @param bean the bean to generate a string for, not null * @return the bean as a map, not null */ public static Map flatten(Bean bean) { var propertyMap = bean.metaBean().metaPropertyMap(); var map = new LinkedHashMap(propertyMap.size()); for (var entry : propertyMap.entrySet()) { map.put(entry.getKey(), entry.getValue().get(bean)); } return Collections.unmodifiableMap(map); } //----------------------------------------------------------------------- /** * Copies properties from a bean to a different bean type. *

* This copies each non-null property value from the source bean to the destination builder * provided that the destination builder supports the property name and the type is compatible. * * @param the type of the bean to create * @param sourceBean the bean to copy from, not null * @param destType the type of the destination bean, not null * @return the copied bean as a builder * @throws RuntimeException if unable to copy a property */ public static BeanBuilder copy(Bean sourceBean, Class destType) { var destMeta = MetaBean.of(destType); @SuppressWarnings("unchecked") var destBuilder = (BeanBuilder) destMeta.builder(); return copyInto(sourceBean, destMeta, destBuilder); } /** * Copies properties from a bean to a builder, which may be for a different type. *

* This copies each non-null property value from the source bean to the destination builder * provided that the destination builder supports the property name and the type is compatible. * * @param the type of the bean to create * @param sourceBean the bean to copy from, not null * @param destMeta the meta bean of the destination, not null * @param destBuilder the builder to populate, not null * @return the updated builder * @throws RuntimeException if unable to copy a property */ public static BeanBuilder copyInto(Bean sourceBean, MetaBean destMeta, BeanBuilder destBuilder) { var sourceMeta = sourceBean.metaBean(); for (var sourceProp : sourceMeta.metaPropertyIterable()) { if (destMeta.metaPropertyExists(sourceProp.name())) { var destProp = destMeta.metaProperty(sourceProp.name()); if (destProp.propertyType().isAssignableFrom(sourceProp.propertyType())) { var sourceValue = sourceProp.get(sourceBean); if (sourceValue != null) { destBuilder.set(destProp, sourceValue); } } } } return destBuilder; } //----------------------------------------------------------------------- /** * Deep clones an array. *

* This performs a deep clone and handles multi-dimensional arrays. * There is no protection against cycles in the object graph beyond {@code StackOverflowError}. *

* Unfortunately, primitive arrays don't play nicely with generics, thus callers must cast the result. * * @param original the original array to clone, null returns null * @return the cloned array, null if null input * @throws IllegalArgumentException if the original object is not an array * @since 2.12.0 */ @SuppressWarnings("unchecked") public static Object cloneArray(Object original) { if (original == null) { return null; } int len = Array.getLength(original); Class arrayType = original.getClass().getComponentType(); Object copy = Array.newInstance(arrayType, len); for (int i = 0; i < len; i++) { Array.set(copy, i, Cloner.INSTANCE.clone(Array.get(original, i))); } return copy; } /** * Deep clones a bean, without cloning an {@code ImmutableBean}. *

* This performs a deep clone. There is no protection against cycles in * the object graph beyond {@code StackOverflowError}. * * @param the type of the bean * @param original the original bean to clone, null returns null * @return the cloned bean, null if null input */ public static T clone(T original) { if (original == null || original instanceof ImmutableBean) { return original; } return cloneAlways(original); } /** * Deep clones a bean always. *

* This performs a deep clone. There is no protection against cycles in * the object graph beyond {@code StackOverflowError}. * This differs from {@link #clone()} in that immutable beans are also cloned. * * @param the type of the bean * @param original the original bean to clone, not null * @return the cloned bean, not null */ public static T cloneAlways(T original) { @SuppressWarnings("unchecked") var builder = (BeanBuilder) original.metaBean().builder(); for (var mp : original.metaBean().metaPropertyIterable()) { if (mp.style().isBuildable()) { var value = mp.get(original); builder.set(mp.name(), Cloner.INSTANCE.clone(value)); } } return builder.build(); } //----------------------------------------------------------------------- /** * Checks if the value is not null, throwing an exception if it is. * * @param value the value to check, may be null * @param propertyName the property name, should not be null * @throws IllegalArgumentException if the value is null */ public static void notNull(Object value, String propertyName) { if (value == null) { throw new IllegalArgumentException(notNullMsg(propertyName)); } } // extracted from notNull(Object,String) to aid hotspot inlining private static String notNullMsg(String propertyName) { return "Argument '" + propertyName + "' must not be null"; } /** * Checks if the value is not blank, throwing an exception if it is. *

* Validate that the specified argument is not null and has at least one non-whitespace character. * * @param value the value to check, may be null * @param propertyName the property name, should not be null * @throws IllegalArgumentException if the value is null or empty */ public static void notBlank(String value, String propertyName) { if (value == null || value.isBlank()) { throw new IllegalArgumentException(notEmpty(propertyName)); } } /** * Checks if the value is not empty, throwing an exception if it is. * * @param value the value to check, may be null * @param propertyName the property name, should not be null * @throws IllegalArgumentException if the value is null or empty */ public static void notEmpty(String value, String propertyName) { if (value == null || value.isEmpty()) { throw new IllegalArgumentException(notEmpty(propertyName)); } } // extracted from notEmpty(?,String) to aid hotspot inlining private static String notEmpty(String propertyName) { return "Argument '" + propertyName + "' must not be empty"; } /** * Checks if the collection value is not empty, throwing an exception if it is. * * @param value the value to check, may be null * @param propertyName the property name, should not be null * @throws IllegalArgumentException if the value is null or empty */ public static void notEmpty(Collection value, String propertyName) { if (value == null || value.isEmpty()) { throw new IllegalArgumentException(notEmpty(propertyName)); } } /** * Checks if the map value is not empty, throwing an exception if it is. * * @param value the value to check, may be null * @param propertyName the property name, should not be null * @throws IllegalArgumentException if the value is null or empty */ public static void notEmpty(Map value, String propertyName) { if (value == null || value.isEmpty()) { throw new IllegalArgumentException(notEmpty(propertyName)); } } //----------------------------------------------------------------------- /** * Extracts the collection content type as a {@code Class} from a property. *

* This method allows the resolution of generics in certain cases. * * @param prop the property to examine, not null * @return the collection content type, null if unable to determine or type has no generic parameters */ public static Class collectionType(Property prop) { return collectionType(prop.metaProperty(), prop.bean().getClass()); } /** * Extracts the collection content type as a {@code Class} from a meta-property. *

* The target type is the type of the object, not the declaring type of the meta-property. * * @param prop the property to examine, not null * @param contextClass the context class to evaluate against, not null * @return the collection content type, null if unable to determine or type has no generic parameters */ public static Class collectionType(MetaProperty prop, Class contextClass) { return extractTypeClass(prop, contextClass, 1, 0); } /** * Extracts the map value type generic type parameters as a {@code Class} from a meta-property. *

* The target type is the type of the object, not the declaring type of the meta-property. *

* This is used when the collection generic parameter is a map or collection. * * @param prop the property to examine, not null * @param contextClass the context class to evaluate against, not null * @return the collection content type generic parameters, empty if unable to determine, no nulls */ public static List> collectionTypeTypes(MetaProperty prop, Class contextClass) { var type = extractType(prop, contextClass, 1, 0); return extractTypeClasses(type, contextClass); } /** * Extracts the map key type as a {@code Class} from a meta-property. * * @param prop the property to examine, not null * @return the map key type, null if unable to determine or type has no generic parameters */ public static Class mapKeyType(Property prop) { return mapKeyType(prop.metaProperty(), prop.bean().getClass()); } /** * Extracts the map key type as a {@code Class} from a meta-property. *

* The target type is the type of the object, not the declaring type of the meta-property. * * @param prop the property to examine, not null * @param contextClass the context class to evaluate against, not null * @return the map key type, null if unable to determine or type has no generic parameters */ public static Class mapKeyType(MetaProperty prop, Class contextClass) { return extractTypeClass(prop, contextClass, 2, 0); } /** * Extracts the map value type as a {@code Class} from a meta-property. * * @param prop the property to examine, not null * @return the map value type, null if unable to determine or type has no generic parameters */ public static Class mapValueType(Property prop) { return mapValueType(prop.metaProperty(), prop.bean().getClass()); } /** * Extracts the map value type as a {@code Class} from a meta-property. *

* The target type is the type of the object, not the declaring type of the meta-property. * * @param prop the property to examine, not null * @param contextClass the context class to evaluate against, not null * @return the map value type, null if unable to determine or type has no generic parameters */ public static Class mapValueType(MetaProperty prop, Class contextClass) { return extractTypeClass(prop, contextClass, 2, 1); } /** * Extracts the map value type generic type parameters as a {@code Class} from a meta-property. *

* The target type is the type of the object, not the declaring type of the meta-property. *

* This is used when the map value generic parameter is a map or collection. * * @param prop the property to examine, not null * @param contextClass the context class to evaluate against, not null * @return the map value type generic parameters, empty if unable to determine, no nulls */ public static List> mapValueTypeTypes(MetaProperty prop, Class contextClass) { var type = extractType(prop, contextClass, 2, 1); return extractTypeClasses(type, contextClass); } /** * Low-level method to extract generic type information. * * @param prop the property to examine, not null * @param contextClass the context class to evaluate against, not null * @param size the number of generic parameters expected * @param index the index of the generic parameter * @return the type, null if unable to determine or type has no generic parameters */ public static Class extractTypeClass(MetaProperty prop, Class contextClass, int size, int index) { return eraseToClass(extractType(prop, contextClass, size, index)); } private static Type extractType(MetaProperty prop, Class contextClass, int size, int index) { var genType = prop.propertyGenericType(); if (genType instanceof ParameterizedType pt) { var types = pt.getActualTypeArguments(); if (types.length == size) { var type = types[index]; if (type instanceof WildcardType wtype) { if (wtype.getLowerBounds().length == 0 && wtype.getUpperBounds().length > 0) { type = wtype.getUpperBounds()[0]; } } if (type instanceof TypeVariable tvar) { type = resolveGenerics(tvar, contextClass); } return type; } } return null; } private static List> extractTypeClasses(Type type, Class contextClass) { var result = new ArrayList>(); if (type != null) { if (type instanceof ParameterizedType pt) { var actualTypes = pt.getActualTypeArguments(); for (var actualType : actualTypes) { if (actualType instanceof TypeVariable tvar) { actualType = resolveGenerics(tvar, contextClass); } var cls = eraseToClass(actualType); result.add(cls != null ? cls : Object.class); } } } return result; } // cache the type variable lookup by Class private static final ClassValue> RESOLVED_TYPE_VARIABLES = new ClassValue<>() { @Override protected Map computeValue(Class contextClass) { var resolved = new HashMap(); findTypeVars(contextClass, resolved); if (resolved.size() > 1) { // simplify, eg 'T=N, N=String' is simplified to 'T=String, N=String' for (var entry : resolved.entrySet()) { var value = entry.getValue(); while (resolved.containsKey(value)) { value = resolved.get(value); } entry.setValue(value); } } return Collections.unmodifiableMap(resolved); } private void findTypeVars(Type type, HashMap resolved) { if (type instanceof Class cls) { // check parent class and interfaces findTypeVars(cls.getGenericSuperclass(), resolved); for (var genInterface : cls.getGenericInterfaces()) { findTypeVars(genInterface, resolved); } } else if (type instanceof ParameterizedType pt) { // find actual types that have been captured var actualTypeArguments = pt.getActualTypeArguments(); // find type variables declared in source code var rawType = eraseToClass(pt.getRawType()); var typeParameters = rawType.getTypeParameters(); for (var i = 0; i < actualTypeArguments.length; i++) { resolved.put(typeParameters[i], actualTypeArguments[i]); } findTypeVars(rawType, resolved); } } }; // resolve generic type variables // if a subclass is defined as 'extends Foo' and the superclass is 'Foo' // then we know that 'T = String' in the context of the subclass // NOTE: this may return a type variable static Type resolveGenerics(TypeVariable typevar, Class contextClass) { var resolved = RESOLVED_TYPE_VARIABLES.get(contextClass); return resolved.getOrDefault(typevar, typevar); } // erases a Type to a Class static Class eraseToClass(Type type) { return switch (type) { case null -> null; case Class cls -> cls; case ParameterizedType parameterizedType -> eraseToClass(parameterizedType.getRawType()); case GenericArrayType arrType -> { var componentType = arrType.getGenericComponentType(); var componentClass = eraseToClass(componentType); yield componentClass != null ? componentClass.arrayType() : null; } case TypeVariable tvar -> { var bounds = tvar.getBounds(); yield bounds.length == 0 ? Object.class : eraseToClass(bounds[0]); } case WildcardType wild -> { var bounds = wild.getUpperBounds(); yield bounds.length == 0 ? Object.class : eraseToClass(bounds[0]); } default -> null; }; } //------------------------------------------------------------------------- /** * Checks if two beans are equal ignoring one or more properties. *

* This version of {@code equalIgnoring} only checks properties at the top level. * For example, if a {@code Person} bean contains an {@code Address} bean then * only properties on the {@code Person} bean will be checked against the ignore list. * * @param bean1 the first bean, not null * @param bean2 the second bean, not null * @param properties the properties to ignore, not null * @return true if equal * @throws IllegalArgumentException if inputs are null */ public static boolean equalIgnoring(Bean bean1, Bean bean2, MetaProperty... properties) { JodaBeanUtils.notNull(bean1, "bean1"); JodaBeanUtils.notNull(bean2, "bean2"); JodaBeanUtils.notNull(properties, "properties"); if (bean1 == bean2) { return true; } if (bean1.getClass() != bean2.getClass()) { return false; } return switch (properties.length) { case 0 -> bean1.equals(bean2); case 1 -> { var ignored = properties[0]; for (var mp : bean1.metaBean().metaPropertyIterable()) { if (!ignored.equals(mp) && !JodaBeanUtils.equal(mp.get(bean1), mp.get(bean2))) { yield false; } } yield true; } default -> { var ignored = Set.of(properties); for (var mp : bean1.metaBean().metaPropertyIterable()) { if (!ignored.contains(mp) && !JodaBeanUtils.equal(mp.get(bean1), mp.get(bean2))) { yield false; } } yield true; } }; } //----------------------------------------------------------------------- /** * Returns an iterator over all the beans contained within the bean. *

* The iterator is a depth-first traversal of the beans within the specified bean. * The first returned bean is the specified bean. * Beans within collections will be returned. *

* A cycle in the bean structure will cause an infinite loop. * * @param bean the bean to iterate over, not null * @return the iterator, not null */ public static Iterator beanIterator(Bean bean) { return new BeanIterator(bean); } //------------------------------------------------------------------------- /** * Chains two meta-properties together. *

* The resulting function takes an instance of a bean, queries using the first * meta-property, then queries the result using the second meta-property. * If the first returns null, the result will be null. * * @param

the type of the result of the chain * @param mp1 the first meta-property, not null * @param mp2 the second meta-property, not null * @return the chain function, not null */ public static

Function chain(MetaProperty mp1, MetaProperty

mp2) { notNull(mp1, "MetaProperty 1"); notNull(mp1, "MetaProperty 2"); return b -> { var first = mp1.get(b); return first != null ? mp2.get(first) : null; }; } /** * Chains a function to a meta-property. *

* The resulting function takes an instance of a bean, queries using the first * function, then queries the result using the second meta-property. * If the first returns null, the result will be null. * * @param

the type of the result of the chain * @param fn1 the first meta-property, not null * @param mp2 the second meta-property, not null * @return the chain function, not null */ public static

Function chain(Function fn1, MetaProperty

mp2) { notNull(fn1, "Function 1"); notNull(fn1, "MetaProperty 2"); return b -> { var first = fn1.apply(b); return first != null ? mp2.get(first) : null; }; } //------------------------------------------------------------------------- /** * Obtains a comparator for the specified bean query. *

* The result of the query must be {@link Comparable}. *

* To use this with a meta-property append {@code ::get} to the meta-property, * for example {@code Address.meta().street()::get}. * * @param query the query to use, not null * @param ascending true for ascending, false for descending * @return the comparator, not null */ public static Comparator comparator(Function query, boolean ascending) { return (ascending ? comparatorAscending(query) : comparatorDescending(query)); } /** * Obtains an ascending comparator for the specified bean query. *

* The result of the query must be {@link Comparable}. * * @param query the query to use, not null * @return the comparator, not null */ public static Comparator comparatorAscending(Function query) { Objects.requireNonNull(query, "query must not be null"); return new Comp(query); } /** * Obtains a descending comparator for the specified bean query. *

* The result of the query must be {@link Comparable}. * * @param query the query to use, not null * @return the comparator, not null */ public static Comparator comparatorDescending(Function query) { Objects.requireNonNull(query, "query must not be null"); return Collections.reverseOrder(new Comp(query)); } //------------------------------------------------------------------------- /** * Comparator. */ private static final class Comp implements Comparator { private final Function query; private Comp(Function query) { this.query = query; } @Override public int compare(Bean bean1, Bean bean2) { @SuppressWarnings("unchecked") var value1 = (Comparable) query.apply(bean1); Object value2 = query.apply(bean2); return value1.compareTo(value2); } } //------------------------------------------------------------------------- /** * Clones an object. */ @SuppressWarnings({"rawtypes", "unchecked"}) private static class Cloner { public static final Cloner INSTANCE = getInstance(); private static Cloner getInstance() { try { ImmutableGrid.of(); // check if class is available return new CollectCloner(); } catch (Exception | LinkageError ex) { try { ImmutableMultiset.of(); // check if class is available return new GuavaCloner(); } catch (Exception | LinkageError ex2) { return new Cloner(); } } } Cloner() { } Object clone(Object value) { return switch (value) { case null -> value; case Bean bean -> cloneAlways(bean); case SortedSet set -> cloneIterable(set, new TreeSet(set.comparator())); case Set set -> cloneIterable(set, LinkedHashSet.newLinkedHashSet(set.size())); case Collection coll -> cloneIterable(coll, new ArrayList(coll.size())); case Iterable iterable -> cloneIterable(iterable, new ArrayList()); case SortedMap map -> cloneMap(map, new TreeMap(map.comparator())); case Map map -> cloneMap(map, LinkedHashMap.newLinkedHashMap(map.size())); case java.util.Date date -> date.clone(); case long[] array -> array.clone(); case int[] array -> array.clone(); case short[] array -> array.clone(); case byte[] array -> array.clone(); case char[] array -> array.clone(); case double[] array -> array.clone(); case float[] array -> array.clone(); case boolean[] array -> array.clone(); case Object[] array -> cloneArray(array); default -> value; }; } Object cloneIterable(Iterable original, Collection cloned) { for (var item : original) { cloned.add(clone(item)); } return cloned; } Object cloneMap(Map original, Map cloned) { for (var item : original.entrySet()) { var entry = (Entry) item; cloned.put(clone(entry.getKey()), clone(entry.getValue())); } return cloned; } Object cloneArray(Object[] originalArray) { var copy = originalArray.clone(); for (var i = 0; i < copy.length; i++) { copy[i] = clone(originalArray[i]); } return copy; } } //------------------------------------------------------------------------- /** * Clones an object. */ @SuppressWarnings({"rawtypes", "unchecked"}) private static class GuavaCloner extends Cloner { GuavaCloner() { } @Override Object clone(Object value) { return switch (value) { case null -> value; case ImmutableCollection coll -> coll; case ImmutableMap map -> map; case ImmutableMultimap map -> map; case ImmutableTable table -> table; case SortedMultiset set -> cloneIterable(set, TreeMultiset.create(set.comparator())); case Multiset mset -> cloneIterable(mset, LinkedHashMultiset.create(mset.size())); case SetMultimap mmap -> cloneMultimap(mmap, LinkedHashMultimap.create()); case ListMultimap mmap -> cloneMultimap(mmap, ArrayListMultimap.create()); case Multimap mmap -> cloneMultimap(mmap, ArrayListMultimap.create()); case BiMap bimap -> cloneMap(bimap, HashBiMap.create(bimap.size())); case Table table -> cloneTable(table, HashBasedTable.create()); default -> super.clone(value); }; } Object cloneMultimap(Multimap original, Multimap cloned) { for (var key : original.keySet()) { var values = original.get(key); for (var value : values) { cloned.put(clone(key), clone(value)); } } return cloned; } Object cloneTable(Table original, Table cloned) { for (var item : original.cellSet()) { var cell = (Table.Cell) item; cloned.put(clone(cell.getRowKey()), clone(cell.getColumnKey()), clone(cell.getValue())); } return cloned; } } //------------------------------------------------------------------------- /** * Clones an object. */ @SuppressWarnings({"rawtypes", "unchecked"}) private static class CollectCloner extends GuavaCloner { CollectCloner() { } @Override Object clone(Object value) { return switch (value) { case null -> value; case ImmutableGrid grid -> grid; case DenseGrid grid -> cloneGrid(grid, DenseGrid.create(grid.rowCount(), grid.columnCount())); case Grid grid -> cloneGrid(grid, SparseGrid.create(grid.rowCount(), grid.columnCount())); default -> super.clone(value); }; } Object cloneGrid(Grid original, Grid cloned) { for (var item : original.cells()) { var cell = (Grid.Cell) item; cloned.put(cell.getRow(), cell.getColumn(), clone(cell.getValue())); } return cloned; } } } ================================================ FILE: src/main/java/org/joda/beans/MetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; /** * A meta-bean, defining those aspects of a bean which are not specific * to a particular instance, such as the type and set of meta-properties. *

* This interface can be thought of as the equivalent of {@link Class} but for beans. * In most cases the meta-bean will be code generated and the concrete class will have additional methods. */ public interface MetaBean { /** * Obtains a meta-bean from a {@code Class}. *

* This will return a meta-bean if it has been registered, or if the class * implements {@link DynamicBean} and has a no-args constructor. * Note that the common case where the meta-bean is registered by a static initializer is handled. * * @param cls the class to get the meta-bean for, not null * @return the meta-bean associated with the class, not null * @throws IllegalArgumentException if unable to obtain the meta-bean */ public static MetaBean of(Class cls) { return MetaBeans.lookup(cls); } /** * Registers a meta-bean. *

* This should be done for all beans in a static factory where possible. * If the meta-bean is dynamic, this method should not be called. * * @param metaBean the meta-bean, not null * @throws IllegalArgumentException if unable to register */ public static void register(MetaBean metaBean) { MetaBeans.register(metaBean); } //----------------------------------------------------------------------- /** * Checks whether this bean is buildable or not. *

* A buildable bean can be constructed using {@link #builder()}. * If this method returns true then {@code builder()} must return a valid builder. * If this method returns false then {@code builder()} must throw {@link UnsupportedOperationException}. * * @return true if this bean is buildable */ public abstract boolean isBuildable(); /** * Creates a bean builder that can be used to create an instance of this bean. *

* The builder is used in two main ways. * The first is to allow immutable beans to be constructed. * The second is to enable automated tools like serialization/deserialization. *

* The builder can be thought of as a {@code Map} of {@link MetaProperty} to value. * Note that the implementation is not necessarily an actual map. * * @return the bean builder, not null * @throws UnsupportedOperationException if the bean cannot be created */ public abstract BeanBuilder builder(); //----------------------------------------------------------------------- /** * Gets the bean name, which is normally the fully qualified class name of the bean. *

* This is primarily used for human-readable output. * * @return the name of the bean, not empty */ public default String beanName() { return beanType().getName(); } /** * Get the type of the bean, represented as a {@code Class}. *

* A {@code MetaBean} can be thought of as the equivalent of {@link Class} but for beans. * This method allows the actual {@code Class} instance of the bean to be obtained. * * @return the type of the bean, not null */ public abstract Class beanType(); //----------------------------------------------------------------------- /** * Counts the number of properties. *

* Each meta-bean manages a single bean with a known set of properties. * This method returns the count of properties. * * @return the number of properties */ public default int metaPropertyCount() { return metaPropertyMap().size(); } /** * Checks if a property exists. *

* Each meta-bean manages a single bean with a known set of properties. * This method checks whether there is a property with the specified name. * * @param propertyName the property name to check, null returns false * @return true if the property exists */ public default boolean metaPropertyExists(String propertyName) { return metaPropertyMap().containsKey(propertyName); } /** * Gets a meta-property by name. *

* Each meta-bean manages a single bean with a known set of properties. * This method returns the property with the specified name. *

* The base interface throws an exception if the name is not recognised. * By contrast, the {@code DynamicMetaBean} interface creates the property on demand. * * @param the property type, optional, enabling auto-casting * @param propertyName the property name to retrieve, not null * @return the meta property, not null * @throws NoSuchElementException if the property name is invalid */ @SuppressWarnings("unchecked") public default MetaProperty metaProperty(String propertyName) { var mp = metaPropertyMap().get(propertyName); if (mp == null) { throw new NoSuchElementException("Unknown property: " + propertyName); } return (MetaProperty) mp; } /** * Gets an iterator of meta-properties. *

* This method returns an {@code Iterable}, which is simpler than a {@code Map}. * As a result, implementations may be able to optimise, and so this method should be * preferred to {@link #metaPropertyMap()} where a choice is possible. * * @return the unmodifiable map of meta property objects, not null */ public default Iterable> metaPropertyIterable() { return metaPropertyMap().values(); } /** * Gets the map of meta-properties, keyed by property name. *

* Where possible, use {@link #metaPropertyIterable()} instead as it typically has better performance. * * @return the unmodifiable map of meta property objects, not null */ public abstract Map> metaPropertyMap(); /** * Gets the annotations associated with this bean. *

* The annotations are queried from the bean. * This is typically accomplished by querying the annotations of an underlying * {@link Class} however any strategy is permitted. *

* If the implementation has a mutable set of annotations, then the result of * this method must stream over those annotations in existence when this method * is called to avoid concurrency issues. *

* The default implementation uses the annotations from {@link #beanType()}. * * @return the annotations, unmodifiable, not null */ public default List annotations() { return List.of(beanType().getAnnotations()); } /** * Gets an annotation from the bean. *

* The annotations are queried from the bean. * This is typically accomplished by querying the annotations of an underlying * {@link Class} however any strategy is permitted. * * @param the annotation type * @param annotationClass the annotation class to find, not null * @return the annotation, not null * @throws NoSuchElementException if the annotation is not specified */ @SuppressWarnings("unchecked") public default A annotation(Class annotationClass) { var annotations = annotations(); for (var annotation : annotations) { if (annotationClass.isInstance(annotation)) { return (A) annotation; } } throw new NoSuchElementException("Unknown annotation: " + annotationClass.getName()); } /** * Finds an optional annotation from the property. *

* The annotations are queried from the property. * This is typically accomplished by querying the annotations of the underlying * instance variable however any strategy is permitted. * * @param the annotation type * @param annotationClass the annotation class to find, not null * @return the annotation, empty if not found * @since 2.11.0 */ @SuppressWarnings("unchecked") public default Optional annotationOpt(Class annotationClass) { var annotations = annotations(); for (var annotation : annotations) { if (annotationClass.isInstance(annotation)) { return Optional.of((A) annotation); } } return Optional.empty(); } } ================================================ FILE: src/main/java/org/joda/beans/MetaBeanProvider.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A provider of {@link MetaBean} instances for bean classes. */ public interface MetaBeanProvider { /** * Returns the meta bean for the class or null if no meta bean can be found. * * @param cls the class for which the meta bean is required * @return the meta bean for the class or null if no meta bean can be found */ MetaBean findMetaBean(Class cls); } ================================================ FILE: src/main/java/org/joda/beans/MetaBeans.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.joda.beans.impl.RecordBean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.impl.map.MapBean; /** * Utilities for registered meta-beans. */ final class MetaBeans { /** * The cache of meta-beans. */ private static final ConcurrentHashMap, MetaBean> META_BEANS = new ConcurrentHashMap<>(); // not a ClassValue, as entries are registered manually /** * The cache of meta-bean providers; access is guarded by a lock on {@code MetaBeans.class}. */ private static final Map, MetaBeanProvider> META_BEAN_PROVIDERS = new HashMap<>(); // not a ClassValue, as it is not on the fast path /** * Restricted constructor. */ private MetaBeans() { } //----------------------------------------------------------------------- /** * Gets the meta-bean for a class. *

* This only works for those beans that have registered their meta-beans. *

* A {@code Class} may use a static initializer block to call {@code register}. * The edge case where the class is loaded but not initialized is handled * by forcing the class to be initialized if necessary. * * @param cls the class to get the meta-bean for, not null * @return the meta-bean, not null * @throws IllegalArgumentException if unable to obtain the meta-bean */ static MetaBean lookup(Class cls) { var meta = META_BEANS.get(cls); if (meta == null) { return metaBeanLookup(cls); } return meta; } // lookup the MetaBean outside the fast path, aiding hotspot inlining private static MetaBean metaBeanLookup(Class cls) { // handle dynamic beans if (cls == FlexiBean.class) { return new FlexiBean().metaBean(); } else if (cls == MapBean.class) { return new MapBean().metaBean(); } else if (DynamicBean.class.isAssignableFrom(cls)) { try { return cls.asSubclass(DynamicBean.class).getDeclaredConstructor().newInstance().metaBean(); } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) { throw new IllegalArgumentException("Unable to find meta-bean for a DynamicBean: " + cls.getName(), ex); } } // a Class can be loaded without being initialized // in this state, the static initializers have not run, and thus the metabean not registered // here initialization is forced to handle that scenario try { cls = Class.forName(cls.getName(), true, cls.getClassLoader()); } catch (ClassNotFoundException | Error ex) { // should be impossible throw new IllegalArgumentException("Unable to find meta-bean: " + cls.getName(), ex); } var meta = META_BEANS.get(cls); if (meta != null) { return meta; } // Synchronization is necessary to prevent a race condition where the same meta-bean is registered twice synchronized (MetaBeans.class) { // Re-check in case the meta-bean has been added by another thread since we checked above meta = META_BEANS.get(cls); if (meta != null) { return meta; } // handle records if (cls.isRecord() && ImmutableBean.class.isAssignableFrom(cls)) { @SuppressWarnings({"rawtypes", "unchecked"}) var metaBean = RecordBean.register((Class) cls, MethodHandles.lookup()); return metaBean; } // handle provider annotations var providerAnnotation = findProviderAnnotation(cls); if (providerAnnotation != null) { var providerClass = providerAnnotation.value(); try { var provider = META_BEAN_PROVIDERS.get(providerClass); if (provider == null) { provider = providerClass.getDeclaredConstructor().newInstance(); META_BEAN_PROVIDERS.put(providerClass, provider); } meta = provider.findMetaBean(cls); if (meta == null) { throw new IllegalArgumentException("Unable to find meta-bean: " + cls.getName()); } register(meta); return meta; } catch (Exception e) { throw new IllegalStateException("Unable to create instance of " + providerClass.getName() + " to provide meta bean for " + cls.getName(), e); } } } throw new IllegalArgumentException("Unable to find meta-bean: " + cls.getName()); } // returns the MetaProvider annotation from the class or null if none can be found. // the class and all its superclasses and interfaces are searched. // if the annotation is found in multiple places then it is undefined which is returned. private static MetaProvider findProviderAnnotation(Class cls) { var providerAnnotation = cls.getAnnotation(MetaProvider.class); if (providerAnnotation != null) { return providerAnnotation; } for (var implementedInterface : cls.getInterfaces()) { providerAnnotation = implementedInterface.getAnnotation(MetaProvider.class); if (providerAnnotation != null) { return providerAnnotation; } } var superclass = cls.getSuperclass(); if (superclass == null || superclass.equals(Object.class)) { return null; } return findProviderAnnotation(superclass); } /** * Registers a meta-bean. *

* This should be done for all beans in a static factory where possible. * If the meta-bean is dynamic, this method should not be called. * * @param metaBean the meta-bean, not null * @throws IllegalArgumentException if unable to register */ static void register(MetaBean metaBean) { var type = metaBean.beanType(); if (META_BEANS.putIfAbsent(type, metaBean) != null) { throw new IllegalArgumentException("Cannot register class twice: " + type.getName()); } } } ================================================ FILE: src/main/java/org/joda/beans/MetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; import org.joda.beans.impl.BasicProperty; import org.joda.convert.StringConvert; /** * A meta-property, defining those aspects of a property which are not specific * to a particular bean, such as the property type and name. * * @param

the type of the property content */ public interface MetaProperty

{ /** * Creates a property that binds this meta-property to a specific bean. *

* This method returns a {@code Property} instance that connects this meta-property to the specified bean. * The result can be queried and passed around without further reference to the bean. * * @param bean the bean to create the property for, not null * @return the property, not null */ public default Property

createProperty(Bean bean) { return BasicProperty.of(bean, this); } //----------------------------------------------------------------------- /** * Gets the meta-bean which owns this meta-property. *

* Each meta-property is fully owned by a single bean. * * @return the meta-bean, not null */ public abstract MetaBean metaBean(); /** * Gets the property name. *

* The JavaBean style methods getFoo() and setFoo() will lead to a property * name of 'foo' and so on. * * @return the name of the property, not empty */ public abstract String name(); /** * Get the type that declares the property, represented as a {@code Class}. *

* This is the type of the bean where the property is declared. * * @return the type declaring the property, not null */ public abstract Class declaringType(); /** * Get the type of the property represented as a {@code Class}. *

* This is the type of the property. * For example, the surname of a person would typically be a {@code String}. * * @return the type of the property, not null */ public abstract Class

propertyType(); /** * Gets the generic types of the property. *

* This provides access to the generic type declared in the source code. * * @return the full generic type of the property, not null */ public abstract Type propertyGenericType(); /** * Gets the resolved generic type of the property. *

* This provides access to the generic type resolved relative to the context class. * * @param contextClass the context class, typically the bean implementation class * @return the resolved generic type of the property, not null */ public default ResolvedType propertyResolvedType(Class contextClass) { return ResolvedType.from(propertyGenericType(), contextClass); } /** * Gets the style of the property, such as read-only, read-write or write-only. *

* Rather than testing against specific values, it is strongly recommended to * call the helper methods on the returned style. * * @return the property style, not null */ public abstract PropertyStyle style(); //----------------------------------------------------------------------- /** * Gets the annotations of the property. *

* The annotations are queried from the property. * This is typically accomplished by querying the annotations of the underlying * instance variable however any strategy is permitted. If the implementation * does not support annotations, an empty list will be returned. * * @return the annotations, unmodifiable, not null */ public abstract List annotations(); /** * Gets an annotation from the property. *

* The annotations are queried from the property. * This is typically accomplished by querying the annotations of the underlying * instance variable however any strategy is permitted. * * @param the annotation type * @param annotationClass the annotation class to find, not null * @return the annotation, not null * @throws NoSuchElementException if the annotation is not found */ @SuppressWarnings("unchecked") public default A annotation(Class annotationClass) { var annotations = annotations(); for (var annotation : annotations) { if (annotationClass.isInstance(annotation)) { return (A) annotation; } } throw new NoSuchElementException("Unknown annotation: " + annotationClass.getName()); } /** * Finds an optional annotation from the property. *

* The annotations are queried from the property. * This is typically accomplished by querying the annotations of the underlying * instance variable however any strategy is permitted. * * @param the annotation type * @param annotationClass the annotation class to find, not null * @return the annotation, empty if not found * @since 2.11.0 */ @SuppressWarnings("unchecked") public default Optional annotationOpt(Class annotationClass) { var annotations = annotations(); for (var annotation : annotations) { if (annotationClass.isInstance(annotation)) { return Optional.of((A) annotation); } } return Optional.empty(); } //----------------------------------------------------------------------- /** * Gets the value of the property for the specified bean. *

* For a standard JavaBean, this is equivalent to calling getFoo() on the bean. * Alternate implementations may perform any logic to obtain the value. * * @param bean the bean to query, not null * @return the value of the property on the specified bean, may be null * @throws ClassCastException if the bean is of an incorrect type * @throws UnsupportedOperationException if the property is write-only */ public abstract P get(Bean bean); /** * Sets the value of the property on the specified bean. *

* The value must be of the correct type for the property. * For a standard JavaBean, this is equivalent to calling setFoo() on the bean. * Alternate implementations may perform any logic to change the value. * * @param bean the bean to update, not null * @param value the value to set into the property on the specified bean, may be null * @throws ClassCastException if the bean is of an incorrect type * @throws ClassCastException if the value is of an invalid type for the property * @throws UnsupportedOperationException if the property is read-only * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses) */ public abstract void set(Bean bean, Object value); /** * Sets the value of the property on the associated bean and returns the previous value. *

* The value must be of the correct type for the property. * This is a combination of the {@code get} and {@code set} methods that matches the definition * of {@code put} in a {@code Map}. * * @param bean the bean to update, not null * @param value the value to set into the property on the specified bean, may be null * @return the old value of the property, may be null * @throws ClassCastException if the bean is of an incorrect type * @throws ClassCastException if the value is of an invalid type for the property * @throws UnsupportedOperationException if the property is read-only * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses) */ public default P put(Bean bean, Object value) { var old = get(bean); set(bean, value); return old; } //----------------------------------------------------------------------- /** * Gets the value of the property for the specified bean converted to a string. *

* This converts the result of {@link #get(Bean)} to a standard format string. * Conversion uses Joda-Convert. * Not all object types can be converted to a string, see Joda-Convert. *

* For a standard JavaBean, this is equivalent to calling getFoo() on the bean. * Alternate implementations may perform any logic to obtain the value. * * @param bean the bean to query, not null * @return the value of the property on the specified bean, may be null * @throws ClassCastException if the bean is of an incorrect type * @throws UnsupportedOperationException if the property is write-only * @throws RuntimeException if the value cannot be converted to a string (use appropriate subclasses) */ public default String getString(Bean bean) { return getString(bean, JodaBeanUtils.stringConverter()); } /** * Gets the value of the property for the specified bean converted to a string. *

* This converts the result of {@link #get(Bean)} to a standard format string using the supplied converter. * Not all object types can be converted to a string, see Joda-Convert. *

* For a standard JavaBean, this is equivalent to calling getFoo() on the bean. * Alternate implementations may perform any logic to obtain the value. * * @param bean the bean to query, not null * @param stringConvert the converter to use, not null * @return the value of the property on the specified bean, may be null * @throws ClassCastException if the bean is of an incorrect type * @throws UnsupportedOperationException if the property is write-only * @throws RuntimeException if the value cannot be converted to a string (use appropriate subclasses) */ public default String getString(Bean bean, StringConvert stringConvert) { var value = get(bean); return stringConvert.convertToString(propertyType(), value); } /** * Sets the value of the property on the specified bean from a string by conversion. *

* This converts the string to the correct type for the property and then sets it * using {@link #set(Bean, Object)}. Conversion uses Joda-Convert. * * @param bean the bean to update, not null * @param value the value to set into the property on the specified bean, may be null * @throws ClassCastException if the bean is of an incorrect type * @throws ClassCastException if the value is of an invalid type for the property * @throws UnsupportedOperationException if the property is read-only * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses) */ public default void setString(Bean bean, String value) { setString(bean, value, JodaBeanUtils.stringConverter()); } /** * Sets the value of the property on the specified bean from a string by conversion. *

* This converts the string to the correct type for the property using the supplied converter and then sets it * using {@link #set(Bean, Object)}. * * @param bean the bean to update, not null * @param value the value to set into the property on the specified bean, may be null * @param stringConvert the converter, not null * @throws ClassCastException if the bean is of an incorrect type * @throws ClassCastException if the value is of an invalid type for the property * @throws UnsupportedOperationException if the property is read-only * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses) */ public default void setString(Bean bean, String value, StringConvert stringConvert) { set(bean, stringConvert.convertFromString(propertyType(), value)); } //----------------------------------------------------------------------- /** * Checks if this meta-property equals another. *

* This compares the property name and declaring type. * It does not compare the property or bean types. * * @param obj the other meta-property, null returns false * @return true if equal */ @Override public abstract boolean equals(Object obj); /** * Returns a suitable hash code. * * @return the hash code */ @Override public abstract int hashCode(); } ================================================ FILE: src/main/java/org/joda/beans/MetaProvider.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Specifies the type of the {@link MetaBeanProvider} that can provide a {@link MetaBean} * for the annotated type. *

* The provider class must have a no-args constructor. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited public @interface MetaProvider { /** * The class that provides the meta-bean. * * @return the class that provides the meta-bean */ Class value(); } ================================================ FILE: src/main/java/org/joda/beans/Property.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A property that is linked to a specific bean. *

* For a JavaBean, this will ultimately wrap a get/set method pair. * Alternate implementations may perform any logic to obtain the value. * * @param

the type of the property content */ public interface Property

{ /** * Gets the bean which owns this property. *

* Each property is fully owned by a single bean. * * @param the bean type * @return the bean, not null */ public abstract B bean(); /** * Gets the meta-property representing the parts of the property that are * common across all instances, such as the name. * * @return the meta-property, not null */ public abstract MetaProperty

metaProperty(); /** * Gets the property name. *

* The JavaBean style methods getFoo() and setFoo() will lead to a property * name of 'foo' and so on. * * @return the name of the property, not empty */ public default String name() { return metaProperty().name(); } //----------------------------------------------------------------------- /** * Gets the value of the property for the associated bean. *

* For a JavaBean, this is the equivalent to calling getFoo() on the bean itself. * Alternate implementations may perform any logic to obtain the value. * * @return the value of the property on the bound bean, may be null * @throws UnsupportedOperationException if the property is write-only */ public default P get() { return metaProperty().get(bean()); } /** * Sets the value of the property on the associated bean. *

* The value must be of the correct type for the property. * See the meta-property for string conversion. * For a standard JavaBean, this is equivalent to calling setFoo() on the bean. * Alternate implementations may perform any logic to change the value. * * @param value the value to set into the property on the bean * @throws ClassCastException if the value is of an invalid type for the property * @throws UnsupportedOperationException if the property is read-only * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses) */ public default void set(Object value) { metaProperty().set(bean(), value); } /** * Sets the value of the property on the associated bean and returns the previous value. *

* This is a combination of the {@code get} and {@code set} methods that matches the definition * of {@code put} in a {@code Map}. * * @param value the value to set into the property on the bean * @return the old value of the property, may be null * @throws ClassCastException if the value is of an invalid type for the property * @throws UnsupportedOperationException if the property is read-only * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses) */ public default P put(Object value) { return metaProperty().put(bean(), value); } //----------------------------------------------------------------------- /** * Checks if this property equals another. *

* This compares the meta-property and value. * It does not consider the property or bean types. * * @param obj the other property, null returns false * @return true if equal */ @Override public abstract boolean equals(Object obj); /** * Returns a suitable hash code. * * @return the hash code */ @Override public abstract int hashCode(); } ================================================ FILE: src/main/java/org/joda/beans/PropertyPath.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static java.util.stream.Collectors.toList; import static org.joda.beans.JodaBeanUtils.notNull; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; /** * A multi-stage property path. *

* This accepts a dot-separated path and queries the bean. * Each dot-separated part of the path is resolved to a meta-property. * Thus the path "foo.bar.baz" is equivalent to {@code bean.getFoo().getBar().getBaz()}. * The path lookup works even if the methods are not public. *

* Each part of the path may contain a suffix, such as {@code []} or {@code []}. * The suffix {@code []} accesses the specified numeric index of an {@code Iterable}. * The suffix {@code []} accesses the specified numeric index of an {@code Map}. * * @param

the type of the result * @since 2.11.0 */ public final class PropertyPath

{ /** * The path entries. */ private final String propertyPath; /** * The result type. */ private final Class

resultType; /** * The path entries. */ private final List pathEntries; /** * Restricted constructor. */ private PropertyPath(String propertyPath, Class

resultType, List pathEntries) { this.propertyPath = propertyPath; this.resultType = resultType; this.pathEntries = pathEntries; } //------------------------------------------------------------------------- /** * Obtains an instance from the path. * * @param

the type of the result * @param propertyPath the path, not null * @param resultType the result type, not null * @return the path * @throws IllegalArgumentException if the path has an invalid format */ public static

PropertyPath

of(String propertyPath, Class

resultType) { notNull(propertyPath, "propertyPath"); notNull(resultType, "resultType"); var split = PathEntry.parse(propertyPath); return new PropertyPath<>(propertyPath, resultType, split); } //------------------------------------------------------------------------- /** * Gets a value by path from the specified bean. *

* This uses the path to query the bean. * There is special handling for {@code Iterable}, {@code Map} and {@code Optional}. * If the path does not match the structure within the bean, optional empty is returned. * If the path finds any nulls, empty lists or empty maps, optional empty is returned. * * @param bean the bean to start from, not null * @return the value, empty if the value is null or the path fails to evaluate correctly */ public Optional

get(Bean bean) { notNull(bean, "bean"); var currentBean = bean; for (var i = 0; i < pathEntries.size() - 1; i++) { var pathEntry = pathEntries.get(i); var obj = pathEntry.get(currentBean); obj = pathEntry.extract(obj); if (obj instanceof Optional optional) { obj = optional.orElse(null); } if (!(obj instanceof Bean newBean)) { return Optional.empty(); } currentBean = newBean; } // last entry, which allows for possibility that resultType = Optional.class var pathEntry = pathEntries.getLast(); var obj = pathEntry.get(currentBean); obj = pathEntry.extract(obj); if (obj == null) { return Optional.empty(); } if (resultType.isInstance(obj)) { return Optional.of(resultType.cast(obj)); } else { if (obj instanceof Optional opt) { obj = opt.orElse(null); } if (resultType.isInstance(obj)) { return Optional.of(resultType.cast(obj)); } return Optional.empty(); } } //------------------------------------------------------------------------- /** * Gets the property path. * * @return the property path */ public String propertyPath() { return propertyPath; } /** * Gets the result type. * * @return the result type */ public Class

resultType() { return resultType; } @Override public boolean equals(Object obj) { return obj instanceof PropertyPath other && this.propertyPath.equals(other.propertyPath) && this.resultType.equals(other.resultType); } @Override public int hashCode() { return propertyPath.hashCode() ^ resultType.hashCode(); } @Override public String toString() { return propertyPath + ": " + resultType.getName(); } //------------------------------------------------------------------------- private static final class PathEntry { private final String propertyName; private final String key; private final int index; static List parse(String propertyPath) { var split = propertyPath.split("\\."); return Stream.of(split) .map(entryStr -> extractEntry(propertyPath, entryStr)) .collect(toList()); } private static PathEntry extractEntry(String propertyPath, String entryStr) { var propName = entryStr; var key = (String) null; var index = 0; var start = entryStr.lastIndexOf('['); if (entryStr.endsWith("]") && start > 0) { key = entryStr.substring(start + 1, entryStr.length() - 1); if (key.isEmpty()) { throw new IllegalArgumentException("Invalid property path, empty key: " + propertyPath); } var firstChar = key.charAt(0); index = -1; if (firstChar == '-' || (firstChar >= '0' && firstChar <= '9')) { try { index = Integer.parseInt(key); } catch (NumberFormatException ex) { // index = -1 } } propName = entryStr.substring(0, start); } return new PathEntry(propName, key, index); } private PathEntry(String propertyName, String key, int index) { this.propertyName = propertyName; this.key = key; this.index = index; } private Object get(Bean bean) { try { return bean.metaBean().metaProperty(propertyName).get(bean); } catch (RuntimeException ex) { return null; } } private Object extract(Object obj) { // maps can be queried using the [key] suffix if desired // an [index] suffix will be queried as a key, not an index if (obj instanceof Map map) { if (key == null) { return extract(map.values()); } else { return map.get(key); } } // lists/sets can be queried using the [index] suffix if desired if (obj instanceof Iterable itr) { if (key != null && index < 0) { return null; } if (obj instanceof List list) { if (index < list.size()) { return list.get(index); } return null; } var it = itr.iterator(); var i = 0; while (it.hasNext() && i < index) { it.next(); i++; } return it.hasNext() ? it.next() : null; } // not a collection if (key != null && !"0".equals(key)) { return null; } return obj; } } } ================================================ FILE: src/main/java/org/joda/beans/PropertyStyle.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * An enumeration of property styles. *

* A property may be read-only, read-write or write-only. * This enumeration models those options. *

* It is strongly recommended to use the methods, not compare against the enum values. */ public enum PropertyStyle { /** * The property can be read and written. */ READ_WRITE, /** * The property is read-only. */ READ_ONLY, /** * The property is write-only. */ WRITE_ONLY, /** * The property is read-only but can be written via the builder. */ READ_ONLY_BUILDABLE, /** * The property is derived. * It is read-only. */ DERIVED, /** * The property is immutable. * It can be read and written via the builder. */ IMMUTABLE; //----------------------------------------------------------------------- /** * Checks whether the property is readable. *

* This checks if the property get method will succeed. * * @return true if the property can be read */ public boolean isReadable() { return this == READ_WRITE || this == READ_ONLY || this == READ_ONLY_BUILDABLE || this == DERIVED || this == IMMUTABLE; } /** * Checks whether the property is writable. *

* This checks if the property set method will succeed. * * @return true if the property can be written */ public boolean isWritable() { return this == READ_WRITE || this == WRITE_ONLY; } /** * Checks whether the property is read-only. *

* This checks if the property get method will succeed and the set method fail. * Read-only, derived and immutable properties will return true. * Note that an immutable property can be written via the builder. * * @return true if the property is derived */ public boolean isReadOnly() { return this == READ_ONLY || this == READ_ONLY_BUILDABLE || this == DERIVED || this == IMMUTABLE; } /** * Checks whether the property can be used in the builder. *

* To check for round-trip behavior, use {@link #isSerializable()}. * * @return true if the property can be used in the builder */ public boolean isBuildable() { return this == READ_WRITE || this == WRITE_ONLY || this == READ_ONLY_BUILDABLE || this == IMMUTABLE; } /** * Checks whether the property is derived. *

* A derived property has no instance variable. * * @return true if the property is derived */ public boolean isDerived() { return this == DERIVED; } /** * Checks whether the property can be serialized in a round-trip. *

* A property that is read-write or immutable can be round-trip serialized. * * @return true if the property is serializable */ public boolean isSerializable() { return this == READ_WRITE || this == READ_ONLY_BUILDABLE || this == IMMUTABLE; } } ================================================ FILE: src/main/java/org/joda/beans/ResolvedType.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static java.util.stream.Collectors.toMap; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.NavigableSet; import java.util.Objects; import java.util.SequencedCollection; import java.util.SequencedMap; import java.util.SequencedSet; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.joda.convert.FromString; import org.joda.convert.ToString; /** * A resolved generic type. *

* This stores a generic type, where any type variables or wildcards have been resolved. * The process of resolving uses a context class to resolve type variables like {@code }. *

* Where type variables cannot be resolved, the type parameter upper bound will be used. * For example, {@code ResolvedType.from(List.class)} returns {@code List} unless a context * class is passed in that extends {@code List} and constrains the type, such as an imaginary class * {@code StringList implements List}. *

* Note that special cases like anonymous classes, hidden classes and specialized enum subclasses * may not be resolved correctly, and validation is deliberately incomplete. * For example, you can create an instance representing {@code List}. *

* The state of this class consists of two parts. * Firstly, there is a {@code Class} representing the raw type, which may be an array. * Secondaly, there is a list of {@code ResolvedType} representing the type arguments. * For example, {@code List[]} will be represented by a {@code Class} of {@code List[]} and * a list of type arguments representing {@code String}. * * @since 3.0.0 */ public final class ResolvedType { /** * The resolved type for {@code Object.class}. */ public static final ResolvedType OBJECT = new ResolvedType(Object.class); /** * The resolved type for {@code String.class}. */ public static final ResolvedType STRING = new ResolvedType(String.class); /** * Pattern for class name. */ private static final Pattern PARSE_CLASS_NAME = Pattern.compile("([^<>, \\[]+)"); /** * Pattern for separator. */ private static final Pattern PARSE_SEPARATOR = Pattern.compile("(([^<>, \\[]+)|<|>|, *|(?:\\[\\])+)"); /** * The short class names. */ private static final Map> NAMES = Set.of( Object.class, String.class, Number.class, Long.class, Integer.class, Short.class, Byte.class, Double.class, Float.class, Character.class, Boolean.class, Void.class, long.class, int.class, short.class, byte.class, double.class, float.class, char.class, boolean.class, void.class, Collection.class, SequencedCollection.class, Set.class, SortedSet.class, NavigableSet.class, SequencedSet.class, List.class, Map.class, SortedMap.class, NavigableMap.class, SequencedMap.class).stream() .collect(toMap(cls -> cls.getSimpleName(), cls -> cls)); /** * The raw type. */ private final Class rawType; /** * The type arguments. */ private final List arguments; /** * Restricted constructor. */ private ResolvedType(Class rawType) { // validation occurs in the calling code this.rawType = rawType; this.arguments = List.of(); } /** * Restricted constructor. */ private ResolvedType(Class rawType, List arguments) { // validation occurs in the calling code this.rawType = rawType; this.arguments = arguments; } //------------------------------------------------------------------------- /** * Parses a {@code ResolvedType} from a formal string. * * @param str the string to parse, not null * @return the resolved type * @throws NullPointerException if null is passed in * @throws IllegalArgumentException if the string cannot be parsed */ @FromString public static ResolvedType parse(String str) { Objects.requireNonNull(str, "str must not be null"); var matcher = PARSE_CLASS_NAME.matcher(str); return parse(matcher, str, 0); } // recursively parse using a matcher that retains the current state private static ResolvedType parse(Matcher matcher, String str, int depth) { if (depth > 255) { throw invalidFormat(str); // no specific error message for infinite recursion guard } // first parse the class name matcher.usePattern(PARSE_CLASS_NAME); if (!matcher.find()) { throw invalidFormat(str); } var name = matcher.group(1); var parsedRawType = parseClassName(name); var typeArgs = new ArrayList(); // then parse any trailing separators matcher.usePattern(PARSE_SEPARATOR); while (matcher.find()) { var separator = matcher.group(1); // parse type arguments, which may be comma separated if (separator.equals("<")) { if (!typeArgs.isEmpty()) { throw invalidFormat(str); } typeArgs.add(parse(matcher, str, depth + 1)); if (!matcher.hasMatch()) { throw invalidFormat(str); } separator = matcher.group(1); while (separator.startsWith(",")) { typeArgs.add(parse(matcher, str, depth + 1)); separator = matcher.group(1); } continue; } // ends the current type argument, at the root level it is an error if (separator.startsWith(",") | separator.equals(">")) { if (depth == 0) { throw invalidFormat(str); } return of(parsedRawType, typeArgs); } // handle an array if (separator.startsWith("[")) { for (var i = 0; i < separator.length() / 2; i++) { parsedRawType = parsedRawType.arrayType(); } continue; } // found some unexpected text throw invalidFormat(str); } return of(parsedRawType, typeArgs); } private static Class parseClassName(String name) { var parsedRawType = NAMES.get(name); if (parsedRawType == null) { try { parsedRawType = Class.forName(name); } catch (ClassNotFoundException ex) { throw new IllegalArgumentException("Unable to parse ResolvedType, class not found: " + name); } } return parsedRawType; } private static IllegalArgumentException invalidFormat(String str) { return new IllegalArgumentException("Unable to parse ResolvedType from '" + str + "', invalid format"); } //------------------------------------------------------------------------- /** * Obtains an instance from a raw type. *

* This factory method is most useful for wrapping types that are not generic, such as {@code String}. * If the input class has generic type parameters, the result will represent the raw type, and the arguments will be empty. * Use {@link #from(Class)} if you want a method that defaults the type parameters to their upper bounds. *

* For example, passing {@code Map.class} to this method will simply wrap the input returning "Map", * and not "Map<Object, Object>". * * @param rawType the raw type, not null * @return the resolved type * @throws NullPointerException if null is passed in */ public static ResolvedType of(Class rawType) { Objects.requireNonNull(rawType, "rawType must not be null"); return new ResolvedType(rawType); } /** * Obtains an instance from a raw type and type arguments. *

* The number of type arguments must match the number of type parameters on the raw type or be empty. * For example, calling this method with {@code Map.class} requires the type arguments to either be * size 2 (generified) or size 0 (raw). * * @param rawType the raw type, not null * @param arguments the type arguments, not null * @return the resolved type * @throws NullPointerException if null is passed in * @throws IllegalArgumentException if the number of arguments do not match the number of generics type parameters or zero */ public static ResolvedType of(Class rawType, ResolvedType... arguments) { Objects.requireNonNull(rawType, "rawType must not be null"); Objects.requireNonNull(arguments, "arguments must not be null"); return of(rawType, List.of(arguments)); } /** * Obtains an instance from a raw type and type arguments. *

* The number of type arguments must match the number of type parameters on the raw type or be empty. * For example, calling this method with {@code Map.class} requires the type arguments to either be * size 2 (generified) or size 0 (raw). * * @param rawType the raw type, not null * @param arguments the type arguments, not null * @return the resolved type * @throws NullPointerException if null is passed in * @throws IllegalArgumentException if the number of arguments do not match the number of generics type parameters or zero */ public static ResolvedType of(Class rawType, List arguments) { Objects.requireNonNull(rawType, "rawType must not be null"); Objects.requireNonNull(arguments, "arguments must not be null"); if (arguments.isEmpty()) { return new ResolvedType(rawType); } var baseType = extractBaseComponentType(rawType); var actualTypeParamCount = baseType.getTypeParameters().length; if (actualTypeParamCount != arguments.size()) { throw invalidTypeParamCount(rawType, actualTypeParamCount, arguments.size()); } return new ResolvedType(rawType, List.copyOf(arguments)); } private static IllegalArgumentException invalidTypeParamCount(Class rawType, int actualCount, int inputCount) { return new IllegalArgumentException( "Class " + rawType.getName() + " has " + actualCount + " type parameters, but " + inputCount + " were supplied"); } //------------------------------------------------------------------------- /** * Obtains an instance from a single-level flat list of raw types. *

* This factory method is most useful for wrapping types with single-level generics like {@code List}, * simply call {@code ofFlat(List.class, String.class)}. *

* Multi-level generic classes can be created, however the nested classes will be raw. * For example, {@code ofFlat(List.class, Optional.class} will resolve to "List<Optional>", * and not "List<Optional<Object>>". * To provide nested generics for {@code Optional} use {@link #of(Class, ResolvedType...)}. * * @param rawType the raw type, not null * @param arguments the type arguments, not null * @return the resolved type * @throws NullPointerException if null is passed in * @throws IllegalArgumentException if the number of arguments do not match the number of generics type parameters or zero */ public static ResolvedType ofFlat(Class rawType, Class... arguments) { Objects.requireNonNull(rawType, "rawType must not be null"); Objects.requireNonNull(arguments, "arguments must not be null"); if (arguments.length == 0) { return new ResolvedType(rawType); } var resolvedArgs = new ResolvedType[arguments.length]; for (var i = 0; i < arguments.length; i++) { resolvedArgs[i] = new ResolvedType(arguments[i]); } return of(rawType, List.of(resolvedArgs)); } //------------------------------------------------------------------------- /** * Obtains an instance from a raw type, providing a default type argument for where the argument is missing. *

* If the input class has generic type parameters, they will be resolved to their upper bound, * typically {@code Object.class}. Use {@link #of(Class)} if you simply want to obtain a wrapper around the raw type. *

* For example, passing {@code Map.class} to this method will determine the upper bounds, returning "Map<Object, Object>". * * @param rawType the raw type, not null * @return the resolved type * @throws NullPointerException if null is passed in */ public static ResolvedType from(Class rawType) { Objects.requireNonNull(rawType, "rawType must not be null"); return resolveClass(rawType, Object.class, false); } /** * Obtains an instance from a type and context class, providing a default type argument for where the argument is missing. *

* The type is typically obtained from reflection, such as from {@link MetaProperty#propertyGenericType()}. * The context class represents the {@code Class} associated with the object being queried, * which is used to resolve type variables like {@code }. * * @param javaType the Java type to resolve, not null * @param contextClass the context class to evaluate against, not null * * @return the resolved type * @throws NullPointerException if null is passed in */ public static ResolvedType from(Type javaType, Class contextClass) { return from(javaType, contextClass, false); } /** * Obtains an instance from a type and context class, where missing type arguments are not defaulted. *

* The type is typically obtained from reflection, such as from {@link MetaProperty#propertyGenericType()}. * The context class represents the {@code Class} associated with the object being queried, * which is used to resolve type variables like {@code }. * * @param javaType the Java type to resolve, not null * @param contextClass the context class to evaluate against, not null * * @return the resolved type * @throws NullPointerException if null is passed in */ public static ResolvedType fromAllowRaw(Type javaType, Class contextClass) { return from(javaType, contextClass, true); } // resolves from the Java Type, optionally resolving raw types private static ResolvedType from(Type javaType, Class contextClass, boolean allowRaw) { Objects.requireNonNull(javaType, "type must not be null"); Objects.requireNonNull(contextClass, "contextClass must not be null"); return switch (javaType) { case Class cls -> resolveClass(cls, contextClass, allowRaw); case ParameterizedType parameterizedType -> resolveParameterizedType(parameterizedType, contextClass, allowRaw); case GenericArrayType arrType -> resolveGenericArrayType(arrType, contextClass, allowRaw); case TypeVariable tvar -> resolveTypeVariable(tvar, contextClass, allowRaw); case WildcardType wild -> resolveWildcard(wild, contextClass, allowRaw); default -> throw unknownGenericTypeClass(javaType); }; } // should never happen, but might do if someone implements Type manually, or the JDK adds a new kind of Type private static IllegalArgumentException unknownGenericTypeClass(Type type) { return new IllegalArgumentException("Unknown generic type class: " + type); } // resolve a Class, either returning the raw type, or selecting the best available type arguments private static ResolvedType resolveClass(Class cls, Class contextClass, boolean allowRaw) { if (allowRaw) { return new ResolvedType(cls); } var baseType = extractBaseComponentType(cls); var typeVariables = baseType.getTypeParameters(); var typeArguments = new ResolvedType[typeVariables.length]; for (var i = 0; i < typeArguments.length; i++) { typeArguments[i] = resolveTypeVariable(typeVariables[i], contextClass, allowRaw); } return new ResolvedType(cls, List.of(typeArguments)); } // resolve things like List private static ResolvedType resolveParameterizedType(ParameterizedType parameterizedType, Class contextClass, boolean allowRaw) { var actualTypeArguments = parameterizedType.getActualTypeArguments(); var typeArguments = new ResolvedType[actualTypeArguments.length]; for (var i = 0; i < typeArguments.length; i++) { typeArguments[i] = from(actualTypeArguments[i], contextClass, allowRaw); } // all known instances of ParameterizedType return Class return new ResolvedType((Class) parameterizedType.getRawType(), List.of(typeArguments)); } // resolve things like Optional[] private static ResolvedType resolveGenericArrayType(GenericArrayType arrType, Class contextClass, boolean allowRaw) { var componentType = arrType.getGenericComponentType(); // Optional var componentResolvedType = from(componentType, contextClass, allowRaw); // Optional var rawType = componentResolvedType.getRawType(); // Optional return new ResolvedType(rawType.arrayType(), componentResolvedType.getArguments()); } // resolve things like > private static ResolvedType resolveTypeVariable(TypeVariable tvar, Class contextClass, boolean allowRaw) { var resolved = JodaBeanUtils.resolveGenerics(tvar, contextClass); if (resolved instanceof TypeVariable unresolved) { var bounds = unresolved.getBounds(); return bounds.length > 0 ? resolveGenericBound(bounds[0], allowRaw) : OBJECT; } return from(resolved, contextClass, allowRaw); } // resolve things like > private static ResolvedType resolveGenericBound(Type bound, boolean allowRaw) { return switch (bound) { case Class cls -> resolveClass(cls, Object.class, allowRaw); case ParameterizedType pt -> { var rawType = JodaBeanUtils.eraseToClass(pt.getRawType()); var typeArgs = pt.getActualTypeArguments(); var resolvedTypeArgs = new ResolvedType[typeArgs.length]; if (typeArgs.length == 0) { yield resolveClass(rawType, Object.class, allowRaw); // ignore weird situations } for (var i = 0; i < typeArgs.length; i++) { resolvedTypeArgs[i] = typeArgs[i] instanceof TypeVariable ? OBJECT : // resolve > into Comparable resolveGenericBound(typeArgs[i], allowRaw); } yield of(rawType, resolvedTypeArgs); } default -> resolveClass(JodaBeanUtils.eraseToClass(bound), Object.class, allowRaw); // ignore weird situations }; } // resolves a wildcard private static ResolvedType resolveWildcard(WildcardType wild, Class contextClass, boolean allowRaw) { var bounds = wild.getUpperBounds(); return bounds.length == 0 ? OBJECT : from(bounds[0], contextClass, allowRaw); } //------------------------------------------------------------------------- /** * Gets the raw type. *

* Gets the {@code Class} object representing the resolved type without generic type arguments. * For example, {@code Optional} will return {@code Optional}, * and {@code List[]} will return {@code List[]}. * * @return the raw type, may be a primitive type or an array type, not null */ public Class getRawType() { return rawType; } /** * Gets the type arguments, empty if the type is not a parameterized type or a generic array type. * * @return the type arguments, not null */ public List getArguments() { return arguments; } /** * Gets the matching type argument or the default value of {@code Object}. *

* No check is performed to see if the index is valid for the raw type. * For example, you could request index 3 from a {@code Map}. * * @param index the index of the generic parameter * @return the type, defaulted to Object */ public ResolvedType getArgumentOrDefault(int index) { if (index < 0 || index >= arguments.size()) { return OBJECT; } return arguments.get(index); } //------------------------------------------------------------------------- /** * Checks whether this is a parameterized generic type, irrespective of whether the type arguments are known. *

* For example, {@code List} and {@code List} return true, while {@code String} returns false. *

* If this type is an array, the result is based on the {@linkplain #toBaseComponentType() base component type}. * * @return true if this is a type with generic type parameters */ public boolean isParameterized() { return extractBaseComponentType(rawType).getTypeParameters().length != 0; } /** * Checks whether this type is raw, which is a type that has missing type arguments. *

* For example, {@code List} returns true, while {@code List} and {@code String} return false. *

* If this type is an array, the result is based on the {@linkplain #toBaseComponentType() base component type}. * * @return true if this is a parameterized generic type but the type arguments are empty */ public boolean isRaw() { return arguments.isEmpty() && extractBaseComponentType(rawType).getTypeParameters().length != 0; } /** * Checks whether this type is a primitive type. *

* An array of primitives will return false. * Consider calling {@link #toBaseComponentType()} first to check for primitive arrays. * * @return true if this is one of the 8 primitive types or void */ public boolean isPrimitive() { return rawType.isPrimitive(); } /** * Checks whether this type is an array type. * * @return true if this is an array type */ public boolean isArray() { return rawType.isArray(); } //------------------------------------------------------------------------- /** * Converts this type to be raw, effectively dropping the generics. *

* This operates on all kinds of {@code ResolvedType}, including arrays and primitives. * If this type has type arguments, the result does not. * * @return the underlying raw type, as a {@code ResolvedType} */ public ResolvedType toRaw() { return arguments.isEmpty() ? this : new ResolvedType(rawType); } /** * Converts this type to the boxed equivalent. *

* If this type is one of the nine primitive types, the equivalent box is returned. * Otherwise, {@code this} is returned. * * @return the equivalent boxed type */ public ResolvedType toBoxed() { return rawType.isPrimitive() ? boxed() : this; } private ResolvedType boxed() { if (rawType == int.class) { return ResolvedType.of(Integer.class); } else if (rawType == long.class) { return ResolvedType.of(Long.class); } else if (rawType == double.class) { return ResolvedType.of(Double.class); } else if (rawType == boolean.class) { return ResolvedType.of(Boolean.class); } else if (rawType == byte.class) { return ResolvedType.of(Byte.class); } else if (rawType == char.class) { return ResolvedType.of(Character.class); } else if (rawType == short.class) { return ResolvedType.of(Short.class); } else if (rawType == float.class) { return ResolvedType.of(Float.class); } else { return ResolvedType.of(Void.class); } } /** * Converts this type to the equivalent Java {@code Type}. *

* The resulting {@code Type} will be a {@code Class}, {@code ParameterizedType} or {@code GenericArrayType}. * If this represents a raw parameterized type, the result will be the raw {@code Class}. * * @return the equivalent Java type */ public Type toJavaType() { if (arguments.isEmpty()) { return rawType; } if (rawType.isArray()) { var componentType = toComponentType().toJavaType(); return new DynamicGenericArrayType(componentType); } else { var argumentList = arguments.stream() .map(ResolvedType::toJavaType) .toArray(Type[]::new); return new DynamicParameterizedType(rawType, argumentList); } } //------------------------------------------------------------------------- /** * Returns the component type, dropping the first array dimension if present. *

* The result of this method consists of the component type of the raw type, with the same type arguments. * For example, calling this method on {@code List[][]} will return {@code List[]}. * If this type is not an array, the result is the equivalent to {@code this}. * * @return the component type, or {@code this} if not an array */ public ResolvedType toComponentType() { var componentType = rawType.getComponentType(); if (componentType == null) { return this; } return new ResolvedType(componentType, arguments); } /** * Returns the base component type, dropping all array dimensions. *

* The result of this method consists of the base component type of the raw type, with the same type arguments. * For example, calling this method on {@code List[][]} will return {@code List}. * If this type is not an array, the result is the equivalent to {@code this}. * * @return the base component type, or {@code this} if not an array */ public ResolvedType toBaseComponentType() { var componentType = rawType.getComponentType(); if (componentType == null) { return this; } return new ResolvedType(extractBaseComponentType(componentType), arguments); } /** * Returns this type as an array type. *

* This returns a new instance with the raw type as an array type, and the same type arguments. * For example, {@code Optional} will be returned as {@code Optional[]}. * * @return the array type * @throws UnsupportedOperationException if this type represents {@code void} * or if the array would have too many dimensions */ public ResolvedType toArrayType() { return new ResolvedType(rawType.arrayType(), arguments); } //------------------------------------------------------------------------- private static Class extractBaseComponentType(Class cls) { var nonArrayType = cls; while (nonArrayType.isArray()) { nonArrayType = nonArrayType.getComponentType(); } return nonArrayType; } //------------------------------------------------------------------------- /** * Checks if this object equals another. * * @param obj the other object * @return true if equal */ @Override public boolean equals(Object obj) { return obj instanceof ResolvedType other && this.rawType == other.rawType && arguments.equals(other.arguments); } /** * Returns a hash code compatible with equals. * * @return the hash code */ @Override public int hashCode() { return rawType.hashCode() ^ arguments.hashCode(); } /** * Returns a formal string representation of the type. * * @return the formal string */ @Override @ToString public String toString() { var baseType = rawType; var suffix = ""; while (baseType.isArray()) { baseType = baseType.getComponentType(); suffix += "[]"; } var shortenedClassName = shortenedClassName(baseType); if (arguments.isEmpty()) { return shortenedClassName + suffix; } else { var builder = new StringBuilder(shortenedClassName).append('<'); for (var i = 0; i < arguments.size(); i++) { if (i > 0) { builder.append(", "); } builder.append(arguments.get(i)); } builder.append('>'); if (rawType.isArray()) { builder.append(suffix); } return builder.toString(); } } private String shortenedClassName(Class cls) { var name = cls.getName(); if (cls.isPrimitive()) { return name; } if (NAMES.containsValue(cls)) { return cls.getSimpleName(); } return name; } //------------------------------------------------------------------------- // the JDK should have a public implementation for this private static final class DynamicParameterizedType implements ParameterizedType { private final Class rawClass; private final Type[] argumentsList; private DynamicParameterizedType(Class rawClass, Type[] typeArguments) { this.rawClass = Objects.requireNonNull(rawClass); this.argumentsList = Objects.requireNonNull(typeArguments).clone(); for (var type : typeArguments) { Objects.requireNonNull(type); } if (typeArguments.length != rawClass.getTypeParameters().length) { throw new IllegalArgumentException("Type parameters do not match"); } } @Override public Type[] getActualTypeArguments() { return argumentsList.clone(); } @Override public Type getRawType() { return rawClass; } @Override public Type getOwnerType() { if (rawClass.isLocalClass()) { return null; } else { return rawClass.getEnclosingClass(); } } @Override public boolean equals(Object obj) { return obj instanceof ParameterizedType other && getRawType().equals(other.getRawType()) && Objects.equals(getOwnerType(), other.getOwnerType()) && Arrays.equals(getActualTypeArguments(), other.getActualTypeArguments()); } @Override public int hashCode() { return Objects.hash(rawClass, Arrays.hashCode(argumentsList)); } @Override public String toString() { var builder = new StringBuilder(rawClass.getName()).append('<'); for (var i = 0; i < argumentsList.length; i++) { if (i > 0) { builder.append(", "); } builder.append(typeToString(argumentsList[i])); } return builder.append('>').toString(); } } //------------------------------------------------------------------------- // the JDK should have a public implementation for this private static final class DynamicGenericArrayType implements GenericArrayType { private final Type componentType; private DynamicGenericArrayType(Type componentType) { this.componentType = Objects.requireNonNull(componentType); } @Override public Type getGenericComponentType() { return componentType; } @Override public boolean equals(Object obj) { return obj instanceof GenericArrayType other && Objects.equals(getGenericComponentType(), other.getGenericComponentType()); } @Override public int hashCode() { return Objects.hashCode(componentType); } @Override public String toString() { return typeToString(componentType) + "[]"; } } private static String typeToString(Type type) { return type instanceof Class cls ? cls.getName() : type.toString(); } } ================================================ FILE: src/main/java/org/joda/beans/TypedMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A meta-bean that captures the type of the bean. *

* It is not possible to add the generic type to all beans, as the type cannot be * refined in hierarchies. This interface is thus useful when there are no subclasses. * * @param the type of the bean */ public interface TypedMetaBean extends MetaBean { @Override public abstract BeanBuilder builder(); @Override public abstract Class beanType(); } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanCodeGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import org.joda.beans.JodaBeanUtils; /** * Code generator for the beans. *

* This reads in a {@code .java} file, parses it, and writes out an updated version. */ public class BeanCodeGen { private static final Pattern PATTERN_OVERRIDE = Pattern.compile(" *[@]Override"); /** * Main method. *

* This calls {@code System.exit}. * * @param args the arguments, not null */ public static void main(String[] args) { BeanCodeGen gen; try { gen = createFromArgs(args); } catch (RuntimeException ex) { System.out.println(ex.getMessage()); System.out.println(); System.out.println("Code generator"); System.out.println(" Usage java org.joda.beans.gen.BeanCodeGen [file]"); System.out.println(" Options"); System.out.println(" -R process all files recursively, default false"); System.out.println(" -indent=tab use a tab for indenting, default 4 spaces"); System.out.println(" -indent=[n] use n spaces for indenting, default 4"); System.out.println(" -prefix=[p] field prefix of p should be removed, no default"); System.out.println(" -eol=[e] end of line: 'lf'/'crlf'/'cr', default System.lineSeparator"); System.out.println(" -generated add @Generated annotation to generated code"); System.out.println(" -config=[f] config file: 'jdk'/'guava', default guava"); System.out.println(" -style=[s] default bean style: 'light'/'minimal'/'full', default smart"); System.out.println(" -verbose=[v] output logging with verbosity from 0 to 3, default 1"); System.out.println(" -nowrite output messages rather than writing, default is to write"); System.exit(0); throw new InternalError("Unreachable"); } try { var changed = gen.process(); System.out.println("Finished, found " + changed + " changed files"); System.exit(0); } catch (Exception ex) { System.out.println(); ex.printStackTrace(System.out); System.exit(1); } } /** * Creates an instance of {@code BeanCodeGen} from arguments. *

* This is intended for tools and does not call {@code System.exit}. * * @param args the arguments, not null * @return the code generator, not null * @throws RuntimeException if unable to create */ public static BeanCodeGen createFromArgs(String[] args) { if (args == null) { throw new IllegalArgumentException("Arguments must not be null"); } var indent = " "; var prefix = ""; var eol = System.lineSeparator(); var defaultStyle = (String) null; var recurse = false; var generatedAnno = false; var verbosity = 1; var write = true; var config = (BeanGenConfig) null; if (args.length == 0) { throw new IllegalArgumentException("No arguments specified"); } for (var i = 0; i < args.length - 1; i++) { var arg = args[i]; if (arg == null) { throw new IllegalArgumentException("Argument must not be null: " + Arrays.toString(args)); } if (arg.startsWith("-indent=tab")) { indent = "\t"; } else if (arg.startsWith("-indent=")) { indent = " ".substring(0, Integer.parseInt(arg.substring(8))); } else if (arg.startsWith("-prefix=")) { prefix = arg.substring(8); } else if (arg.startsWith("-eol=")) { eol = switch (arg.substring(5)) { case "lf" -> "\n"; case "crlf" -> "\r\n"; case "cr" -> "\r"; case "system" -> System.lineSeparator(); default -> throw new IllegalArgumentException("Value of 'eol' must be one of: 'lf', 'crlf', 'cr', 'system'"); }; } else if (arg.equals("-R")) { recurse = true; } else if (arg.equals("-generated")) { if (generatedAnno) { throw new IllegalArgumentException("Argument 'generated' must not be specified twice: " + Arrays.toString(args)); } generatedAnno = true; } else if (arg.startsWith("-config=")) { if (config != null) { throw new IllegalArgumentException("Argument 'config' must not be specified twice: " + Arrays.toString(args)); } config = BeanGenConfig.parse(arg.substring(8)); } else if (arg.startsWith("-style=")) { if (defaultStyle != null) { throw new IllegalArgumentException("Argument 'style' must not be specified twice: " + Arrays.toString(args)); } defaultStyle = arg.substring(7); } else if (arg.startsWith("-verbose=")) { verbosity = Integer.parseInt(arg.substring(9)); } else if (arg.equals("-nowrite")) { write = false; } else { throw new IllegalArgumentException("Unknown argument: " + arg); } } var file = Path.of(args[args.length - 1]); var files = findFiles(file, recurse); if (config == null) { config = BeanGenConfig.parse("guava"); } config.setIndent(indent); config.setPrefix(prefix); config.setEol(eol); if (defaultStyle != null) { config.setDefaultStyle(defaultStyle); } config.setGeneratedAnno(generatedAnno); return new BeanCodeGen(files, config, verbosity, write); } /** * Finds the set of files to process. * * @param parent the root, not null * @param recurse whether to recurse * @return the files, not null */ private static List findFiles(Path parent, boolean recurse) { try (var pathStream = Files.walk(parent, recurse ? Integer.MAX_VALUE : 1)) { return pathStream .filter(path -> path.toString().endsWith(".java")) .map(path -> path.toFile()) .toList(); } catch (IOException ex) { throw new UncheckedIOException(ex); } } //----------------------------------------------------------------------- /** The files to process. */ private final List files; /** The configuration to use. */ private final BeanGenConfig config; /** The verbosity level. */ private final int verbosity; /** Whether to write or not. */ private final boolean write; /** * Creates the generator for a single bean. *

* To generate, use {@link #process()}. * * @param files the files to process, not null * @param config the configuration to use, not null * @param verbosity the verbosity, from 0 to 3 * @param write whether to write or not */ public BeanCodeGen(List files, BeanGenConfig config, int verbosity, boolean write) { JodaBeanUtils.notNull(files, "files"); JodaBeanUtils.notNull(config, "config"); if (verbosity < 0 || verbosity > 3) { throw new IllegalArgumentException("Invalid verbosity: " + verbosity); } this.files = files; this.config = config; this.verbosity = verbosity; this.write = write; } //----------------------------------------------------------------------- /** * Processes the file, recursing as necessary, generating the source code. *

* The number of altered files is returned. * * @return the number of changed files * @throws Exception if an error occurs */ public int process() throws Exception { var changed = 0; for (var file : files) { changed += (processFile(file) != null ? 1 : 0); } return changed; } /** * Processes the file, recursing as necessary, generating the source code. *

* The list of altered files is returned. * * @return the list of changed files, not null * @throws Exception if an error occurs */ public List processFiles() throws Exception { var changed = new ArrayList(); for (var file : files) { var processedFile = processFile(file); if (processedFile != null) { changed.add(processedFile); } } return changed; } /** * Processes the bean, generating the code. * * @param file the file to process, not null * @return not-null if changed * @throws IOException if an error occurs */ private File processFile(File file) throws IOException { var original = Files.readAllLines(file.toPath()); var content = new ArrayList<>(original); var gen = parse(file, content); if (gen.isBean()) { if (verbosity >= 2) { System.out.print(file + " [processing]"); } gen.process(); if (contentDiffers(content, original)) { return writeFileWithLogging(file, content); } else if (verbosity >= 2) { System.out.println(" [no change]"); } } else { gen.processNonBean(); if (contentDiffers(content, original)) { return writeFileWithLogging(file, content); } else if (verbosity == 3) { System.out.println(file + " [ignored]"); } } return null; } // parses the file private BeanGen parse(File file, ArrayList content) { try { var parser = new BeanParser(file, content, config); return parser.parse(); } catch (BeanCodeGenException ex) { throw ex; } catch (Exception ex) { throw new BeanCodeGenException(ex.getMessage(), ex, file); } } // checks to see if the content differs from the original // if the files differ only by @Override lines then they are considered to be equal private boolean contentDiffers(List content, List original) { var contentIndex = 0; var originalIndex = 0; while (contentIndex < content.size() && originalIndex < original.size()) { var contentLine = content.get(contentIndex); var originalLine = original.get(originalIndex); if (contentLine.equals(originalLine)) { // lines match contentIndex++; originalIndex++; } else if (PATTERN_OVERRIDE.matcher(originalLine).matches()) { // original is an @Override line originalIndex++; } else { return true; } } return contentIndex < content.size() || originalIndex < original.size(); } // writes the file with appropriate logging private File writeFileWithLogging(File file, ArrayList content) throws IOException { if (write) { if (verbosity >= 2) { System.out.println(" [writing]"); } else if (verbosity == 1) { System.out.println(file + " [writing]"); } writeFile(file, content); } else { if (verbosity >= 2) { System.out.println(" [changed not written]"); } else if (verbosity == 1) { System.out.println(file + " [changed not written]"); } } return file; } // this uses a customizable EOL character private void writeFile(File file, List content) throws IOException { try (var writer = new FileWriter(file, StandardCharsets.UTF_8)) { for (var line : content) { writer.write(line); writer.write(config.getEol()); } } } } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanCodeGenException.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.io.File; import java.io.Serial; /** * Exception thrown by the code generator. */ public final class BeanCodeGenException extends RuntimeException { /** * Serialization version. */ @Serial private static final long serialVersionUID = 1L; /** * The line number. */ private final int line; /** * The file. */ private final File file; /** * Creates the exception. * * @param message the message * @param file the file that caused the error * @param line the line number */ public BeanCodeGenException(String message, File file, int line) { super("Error in bean: " + file + ", Line: " + line + ", Message: " + message); this.file = file; this.line = line; } /** * Creates the exception. * * @param message the message * @param cause the cause * @param file the file that caused the error */ public BeanCodeGenException(String message, Throwable cause, File file) { super("Error in bean: " + file + ", Line: 0, Message: " + message, cause); this.file = file; this.line = 0; } //----------------------------------------------------------------------- /** * Gets the line number. * * @return the line number */ public File getFile() { return file; } /** * Gets the line number. * * @return the line number */ public int getLine() { return line; } } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanData.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * A bean that can be generated. */ class BeanData { /** The list of current imports. */ private final SortedSet currentImports = new TreeSet<>(); /** The list of new imports. */ private final SortedSet newImports = new TreeSet<>(); /** The last import line. */ private int lastImportLine; /** The bean style. */ private String beanStyle; /** The bean meta scope. */ private String beanMetaScope; /** The bean meta implements. */ private String beanMetaImplements; /** The bean builder scope. */ private String beanBuilderScope; /** The bean builder style. */ private String beanBuilderName; /** The factory method name. */ private String factoryName; /** Whether to cache the hash code. */ private boolean cacheHashCode; /** Whether the class is immutable. */ private boolean immutable; /** Whether the class can be constructed. */ private boolean constructable; /** Whether the class has a manual constructor for immutable beans. */ private int immutableConstructor; /** The method name of the immutable validator. */ private String immutableValidator; /** The method name of the immutable defaults. */ private String immutableDefaults; /** The method name of the immutable pre-build. */ private String immutablePreBuild; /** The style of constructor to generate. */ private int constructorStyle; /** The generated constructor scope. */ private String constructorScope; /** The full type of the bean class. */ private String typeFull; /** The simple name of the bean class. */ private String typeRaw; /** The name clause of the generic. */ private String[] typeGenericName; /** The extends clause of the generic. */ private String[] typeGenericExtends; /** Whether the type is final with no subclasses. */ private boolean typeFinal; /** The scope of the type. */ private String typeScope; /** Whether the type is a root with no bean super-classes. */ private boolean root; /** The full name of the bean superclass. */ private String superTypeFull; /** The simple name of the bean superclass. */ private String superTypeRaw; /** The generic argument of the bean superclass. */ private String superTypeGeneric; /** The list of properties, in the order they are declared. */ private final List properties = new ArrayList<>(); /** The serializable flag. */ private boolean serializable; /** The manual serialization version id flag. */ private boolean manualSerVersionId; /** Does the class have a manual clone. */ private boolean manualClone; /** Does the class have a manual equals or hash code. */ private boolean manualEqualsHashCode; /** Does the class have a manual toString. */ private boolean manualToStringCode; /** The style for Object#clone */ private String cloneStyle; /** * Constructor. */ BeanData() { } /** * Gets the current set of imports. * @return the imports */ public SortedSet getCurrentImports() { return currentImports; } /** * Gets the new imports. * @return the imports */ public SortedSet getNewImports() { return newImports; } /** * Ensures an import is present. * @param cls the class, not null */ public void ensureImport(Class cls) { ensureImport(cls.getName()); } /** * Ensures an import is present. * @param className the class name, not null */ void ensureImport(String className) { if (!currentImports.contains(className)) { newImports.add(className); } } /** * Gets the import insert location. * @return the insert location */ public int getImportInsertLocation() { return lastImportLine; } /** * Sets the import insert location. * @param location the insert location */ public void setImportInsertLocation(int location) { lastImportLine = location; } //----------------------------------------------------------------------- /** * Gets the bean style. * @return the flag */ public String getBeanStyle() { return beanStyle; } /** * Sets the bean style. * @param beanStyle the flag */ public void setBeanStyle(String beanStyle) { this.beanStyle = beanStyle; } /** * Resolves the bean style. * @param defaultStyle the default style */ public void resolveBeanStyle(String defaultStyle) { if ("smart".equals(beanStyle)) { setBeanStyle(defaultStyle); } } /** * Is the bean style indicating that properties should be generated. * @return the flag */ public boolean isBeanStyleValid() { return "full".equals(beanStyle) || "smart".equals(beanStyle) || "minimal".equals(beanStyle) || "light".equals(beanStyle); } /** * Is the bean style indicating that no meta and builder should be generated. * @return the flag */ public boolean isBeanStyleLight() { return "light".equals(beanStyle); } /** * Is the bean style minimal. * @return the flag */ public boolean isBeanStyleMinimal() { return "minimal".equals(beanStyle); } /** * Is the bean style indicating that no meta and builder should be generated. * @return the flag */ public boolean isBeanStyleLightOrMinimal() { return isBeanStyleLight() || isBeanStyleMinimal(); } /** * Is the bean style indicating that properties should be generated. * @return the flag */ public boolean isBeanStyleGenerateProperties() { return "full".equals(beanStyle) || ("smart".equals(beanStyle) && !isImmutable()); } /** * Is the bean style indicating that properties should be generated. * @return the flag */ public boolean isBeanStyleGenerateMetaProperties() { return ("full".equals(beanStyle) || "smart".equals(beanStyle)) && !isMetaScopePrivate(); } //----------------------------------------------------------------------- /** * Gets the bean meta scope. * @return the scope */ public String getBeanMetaScope() { return beanMetaScope; } /** * Sets the bean meta scope. * @param metaScope the scope */ public void setBeanMetaScope(String metaScope) { this.beanMetaScope = metaScope; } /** * Is the meta scope valid. * @return the flag */ public boolean isBeanMetaScopeValid() { return "smart".equals(beanMetaScope) || "private".equals(beanMetaScope) || "package".equals(beanMetaScope) || "public".equals(beanMetaScope); } /** * Gets the effective scope to use in the meta. * @return the scope */ public String getEffectiveMetaScope() { var scope = beanMetaScope; if ("smart".equals(scope)) { scope = typeScope; } return "package".equals(scope) ? "" : scope + " "; } /** * Checks the meta-bean scope. * @return the scope */ public boolean isMetaScopePrivate() { return "private".equals(beanMetaScope) || isBeanStyleLight(); } //----------------------------------------------------------------------- /** * Gets the bean meta implements. * @return the meta implements */ public String getBeanMetaImplements() { return beanMetaImplements; } /** * Sets the bean meta implements. * @param metaImplements the meta implements */ public void setBeanMetaImplements(String metaImplements) { this.beanMetaImplements = metaImplements; } //----------------------------------------------------------------------- /** * Gets the bean builder scope. * @return the scope */ public String getBeanBuilderScope() { return beanBuilderScope; } /** * Sets the bean builder scope. * @param builderScope the scope */ public void setBeanBuilderScope(String builderScope) { this.beanBuilderScope = builderScope; } /** * Is the builder scope valid. * @return the flag */ public boolean isBeanBuilderScopeValid() { return "smart".equals(beanBuilderScope) || "private".equals(beanBuilderScope) || "package".equals(beanBuilderScope) || "public".equals(beanBuilderScope); } /** * Gets the effective scope to use in the builder. * @return the scope */ public String getEffectiveBuilderScope() { var scope = beanBuilderScope; if ("smart".equals(scope)) { scope = typeScope; } return "package".equals(scope) ? "" : scope + " "; } /** * Is the effective scope to use in the builder public. * @return the scope */ public boolean isEffectiveBuilderScopeVisible() { return ("smart".equals(beanBuilderScope) || "public".equals(beanBuilderScope) || "package".equals(beanBuilderScope)) && !isBeanStyleLight(); } /** * Is the scope to use in the builder public. * @return the scope */ public boolean isBuilderScopeVisible() { return "public".equals(beanBuilderScope) || "package".equals(beanBuilderScope); } /** * Is the builder generated * @return true if generated */ public boolean isBuilderGenerated() { return (isImmutable() && isEffectiveBuilderScopeVisible()) || (isMutable() && isBuilderScopeVisible()); } /** * Is the builder generated * @return true if generated */ public boolean isSkipBuilderGeneration() { return (isMutable() && !isBuilderScopeVisible()) || isBeanStyleLight() || isBeanBuilderManual(); } //----------------------------------------------------------------------- /** * Gets the bean builder class name. * @return the class name */ public String getBeanBuilderName() { return beanBuilderName; } /** * Sets the bean builder class name. * @param builderName the class name */ public void setBeanBuilderName(String builderName) { this.beanBuilderName = builderName; } /** * Is the builder style manual. * @return the flag */ public boolean isBeanBuilderManual() { return !beanBuilderName.isEmpty(); } /** * Gets the effective bean builder. * @return the name */ public String getEffectiveBeanBuilderName() { return beanBuilderName.isEmpty() ? getTypeRaw() + ".Builder" : beanBuilderName; } /** * Gets the effective bean builder. * @return the name */ public String getEffectiveMinimalBeanBuilderName() { return beanBuilderName.isEmpty() ? "Builder" : beanBuilderName; } //----------------------------------------------------------------------- /** * Gets the factory name. * @return the factory name */ public boolean isFactoryRequired() { return !factoryName.isEmpty(); } /** * Gets the factory name. * @return the factory name */ public String getFactoryName() { return factoryName; } /** * Sets the factory name. * @param name the factory name */ public void setFactoryName(String name) { factoryName = name; } //----------------------------------------------------------------------- /** * Gets whether to cache the hash code. * @return the flag */ public boolean isCacheHashCode() { return cacheHashCode; } /** * Sets whether to cache the hash code. * @param cacheHashCode the flag */ public void setCacheHashCode(boolean cacheHashCode) { this.cacheHashCode = cacheHashCode; } //----------------------------------------------------------------------- /** * Gets whether property change support is needed. * @return the flag */ public boolean isPropertyChangeSupport() { return properties.stream().anyMatch(PropertyData::isBound); } //----------------------------------------------------------------------- /** * Gets whether the bean is immutable. * @return the flag */ public boolean isImmutable() { return immutable; } /** * Gets whether the bean is mutable. * @return the flag */ public boolean isMutable() { return !immutable; } /** * Sets whether the bean is immutable. * @param immutable the flag */ public void setImmutable(boolean immutable) { this.immutable = immutable; } /** * Checks whether the bean can be constructed. * @return the flag */ public boolean isConstructable() { return constructable; } /** * Sets whether the bean can be constructed. * @param constructable the flag */ public void setConstructable(boolean constructable) { this.constructable = constructable; } /** * Gets whether the bean has a manual constructor to use. * @return the flag, zero for none, one for builder based, two for argument based */ public int getImmutableConstructor() { return immutableConstructor; } /** * Sets whether the bean has a manual constructor to use. * @param manualConstructor the flag */ public void setImmutableConstructor(int manualConstructor) { this.immutableConstructor = manualConstructor; } /** * Gets whether the bean has a validator. * @return the method name */ public String getImmutableValidator() { return immutableValidator; } /** * Sets whether the bean has a validator. * @param immutableValidator the method name */ public void setImmutableValidator(String immutableValidator) { this.immutableValidator = immutableValidator; } /** * Gets whether the bean has an apply defaults method. * @return the method name */ public String getImmutableDefaults() { return immutableDefaults; } /** * Sets whether the bean has an apply defaults method. * @param immutableDefaults the method name */ public void setImmutableDefaults(String immutableDefaults) { this.immutableDefaults = immutableDefaults; } /** * Gets whether the bean has a pre-build method. * @return the method name */ public String getImmutablePreBuild() { return immutablePreBuild; } /** * Sets whether the bean has a pre-build method. * @param immutablePreBuild the method name */ public void setImmutablePreBuild(String immutablePreBuild) { this.immutablePreBuild = immutablePreBuild; } /** * Gets the constructor style to generate. * @return the flag, zero for none, one for builder based, two for argument based */ public int getConstructorStyle() { return constructorStyle; } /** * Sets the constructor style to generate. * @param constructorStyle the constructor style */ public void setConstructorStyle(int constructorStyle) { this.constructorStyle = constructorStyle; } /** * Gets the constructor scope to generate. * @return the scope */ public String getConstructorScope() { return constructorScope; } /** * Sets the constructor scope to generate. * @param constructorScope the constructor scope */ public void setConstructorScope(String constructorScope) { this.constructorScope = constructorScope; } /** * Is the constructor scope valid. * @return true if valid */ public boolean isConstructorScopeValid() { return "smart".equals(constructorScope) || "private".equals(constructorScope) || "package".equals(constructorScope) || "protected".equals(constructorScope) || "public".equals(constructorScope) || "public@ConstructorProperties".equals(constructorScope); } /** * Gets the effective scope to use in the constructor. * @return the scope */ public String getEffectiveConstructorScope() { if ("smart".equals(constructorScope)) { return isTypeFinal() ? "private " : "protected "; } else if ("package".equals(constructorScope)) { return ""; } else if ("public@ConstructorProperties".equals(constructorScope)) { return "public "; } return constructorScope + " "; } /** * Checks if the scope indicates the need for the ConstructorProperties annotation. * @return true if the annotation is needed */ public boolean isConstructorPropertiesAnnotation() { return "public@ConstructorProperties".equals(constructorScope); } /** * Checks whether the bean is serializable. * @return the flag */ public boolean isSerializable() { return serializable; } /** * Sets whether the bean is serializable. * @param serializable the flag */ public void setSerializable(boolean serializable) { this.serializable = serializable; } /** * Checks whether the bean has a manual serialization id. * @return the flag */ public boolean isManualSerializationId() { return manualSerVersionId; } /** * Sets whether the bean has a manual serialization id. * @param manualSerVersionId the flag */ public void setManualSerializationId(boolean manualSerVersionId) { this.manualSerVersionId = manualSerVersionId; } /** * Checks if the clone is manual. * @return true if manual */ public boolean isManualClone() { return manualClone; } /** * Sets if the clone is manual. * @param manualClone true if manual */ public void setManualClone(boolean manualClone) { this.manualClone = manualClone; } /** * Checks if the equals/hashCode is manual. * @return true if manual */ public boolean isManualEqualsHashCode() { return manualEqualsHashCode; } /** * Sets if the equals/hashCode is manual. * @param manualEqualsHashCode true if manual */ public void setManualEqualsHashCode(boolean manualEqualsHashCode) { this.manualEqualsHashCode = manualEqualsHashCode; } /** * Checks if the toString is manual. * @return true if manual */ public boolean isManualToStringCode() { return manualToStringCode; } /** * Sets if the toString is manual. * @param manualToStringCode true if manual */ public void setManualToStringCode(boolean manualToStringCode) { this.manualToStringCode = manualToStringCode; } /** * Gets the clone style. * @return the clone style */ public String getCloneStyle() { return cloneStyle; } /** * Sets the clone style. * @param cloneStyle the clone style */ public void setCloneStyle(String cloneStyle) { this.cloneStyle = cloneStyle; } /** * Is the clone style valid. * @return true if valid */ public boolean isCloneStyleValid() { return "smart".equals(cloneStyle) || "omit".equals(cloneStyle) || "generate".equals(cloneStyle); } /** * Is the clone method to be skipped. * @return true to generate */ public boolean isSkipCloneGeneration() { return ("smart".equals(cloneStyle) && isImmutable()) || "omit".equals(cloneStyle); } /** * Sets the bean type. * @param parts the type to set */ public void setTypeParts(String[] parts) { this.typeFinal = parts[0] != null; this.typeScope = parts[1]; this.typeFull = parts[2]; this.typeRaw = parts[3]; if (parts[8] != null) { this.typeGenericName = new String[] {parts[4], parts[6], parts[8]}; this.typeGenericExtends = new String[3]; this.typeGenericExtends[0] = parts[5] != null ? parts[5] : ""; this.typeGenericExtends[1] = parts[7] != null ? parts[7] : ""; this.typeGenericExtends[2] = parts[9] != null ? parts[9] : ""; } else if (parts[6] != null) { this.typeGenericName = new String[] {parts[4], parts[6]}; this.typeGenericExtends = new String[2]; this.typeGenericExtends[0] = parts[5] != null ? parts[5] : ""; this.typeGenericExtends[1] = parts[7] != null ? parts[7] : ""; } else if (parts[4] != null) { this.typeGenericName = new String[] {parts[4]}; this.typeGenericExtends = new String[1]; this.typeGenericExtends[0] = parts[5] != null ? parts[5] : ""; } else { this.typeGenericName = new String[0]; this.typeGenericExtends = new String[0]; } } /** * Sets the bean superclass type. * @param parts the superclass to set */ public void setSuperTypeParts(String[] parts) { if (parts.length == 1) { this.root = true; this.immutable = "ImmutableBean".equals(parts[0]); this.superTypeFull = ""; this.superTypeRaw = ""; this.superTypeGeneric = ""; } else { this.root = "DirectBean".equals(parts[0]); this.immutable = false; this.superTypeFull = parts[0]; this.superTypeRaw = parts[1]; if (parts[4] != null) { this.superTypeGeneric = parts[2] + ", " + parts[3] + ", " + parts[4]; } else if (parts[3] != null) { this.superTypeGeneric = parts[2] + ", " + parts[3]; } else if (parts[2] != null) { this.superTypeGeneric = parts[2]; } else { this.superTypeGeneric = ""; } } } /** * Gets the modifiable list of properties. * @return the properties, not null */ public List getProperties() { return properties; } /** * Checks if the type is final. * @return true if manual */ public boolean isTypeFinal() { return typeFinal; } /** * Sets if the type is final. * @param typeFinal true if final, false if subclassable */ public void setTypeFinal(boolean typeFinal) { this.typeFinal = typeFinal; } /** * Gets the scope of the type. * @return the scope */ public String getTypeScope() { return typeScope; } //----------------------------------------------------------------------- /** * Checks if this bean is a superclass. * @return true if this is a subclass of another bean */ public boolean isSubClass() { return !root; } /** * Checks if this bean is the root class in a hierarchy. * @return true if this is the root class with no bean superclasses */ public boolean isRootClass() { return root; } /** * Checks if this bean directly extends {@code DirectBean}. * @return true if this extends DirectBean */ public boolean isExtendsDirectBean() { return "DirectBean".equals(superTypeFull); } //----------------------------------------------------------------------- /** * Checks if the bean is parameterised with generics. * @return true if generified */ public boolean isTypeGeneric() { return typeGenericName.length > 0; } /** * Gets the number of generic type parameters. * @return zero if no type parameters, one or two if it has type parameters */ public int getTypeGenericCount() { return typeGenericName.length; } /** * Gets the bean type, such as '{@code Foo}'. * @return the type */ public String getType() { return typeFull; } /** * Gets the parameterisation of the bean including extends clause, such as '{@code }'. * @param includeBrackets whether to include the brackets * @return the generic type, or a blank string if not generic, not null */ public String getTypeGeneric(boolean includeBrackets) { if (!isTypeGeneric()) { return ""; } var result = typeGenericName[0] + typeGenericExtends[0]; if (typeGenericExtends.length > 1) { result += ", " + typeGenericName[1] + typeGenericExtends[1]; if (typeGenericExtends.length > 2) { result += ", " + typeGenericName[2] + typeGenericExtends[2]; } } return includeBrackets && !result.isEmpty() ? '<' + result + '>' : result; } /** * Gets the name of the parameterisation of the bean, such as '{@code }'. * @param includeBrackets whether to include the brackets * @return the generic type name, or a blank string if not generic, not null */ public String getTypeGenericName(boolean includeBrackets) { if (!isTypeGeneric()) { return ""; } var result = typeGenericName[0]; if (typeGenericExtends.length > 1) { result += ", " + typeGenericName[1]; if (typeGenericExtends.length > 2) { result += ", " + typeGenericName[2]; } } return includeBrackets && !result.isEmpty() ? '<' + result + '>' : result; } /** * Gets the diamond operator if generic. * @return the generic type name, or a blank string if not generic, not null */ public String getTypeGenericDiamond() { return isTypeGeneric() ? "<>" : ""; } /** * Gets the type with the diamond operator if generic. * @return the type name, with generic diamond if necessary, not null */ public String getTypeWithDiamond() { return isTypeGeneric() ? getTypeRaw() + "<>" : getTypeRaw(); } /** * Gets the name of the parameterisation of the bean, such as '{@code }'. * @param typeParamIndex the zero-based index of the type parameter * @param includeBrackets whether to include brackets * @return the generic type name, not null */ public String getTypeGenericName(int typeParamIndex, boolean includeBrackets) { var result = typeGenericName[typeParamIndex]; return includeBrackets && !result.isEmpty() ? '<' + result + '>' : result; } /** * Gets the extends clause of the parameterisation of the bean, such as '{@code extends Foo}'. * @param typeParamIndex the zero-based index of the type parameter * @return the generic type extends clause, or a blank string if not generic or no extends, not null */ public String getTypeGenericErased(int typeParamIndex) { var extend = typeGenericExtends[typeParamIndex]; return extend.startsWith(" extends ") ? extend.substring(9) : "Object"; } /** * Gets the extends clause of the parameterisation of the bean, such as '{@code extends Foo}'. * @param typeParamIndex the zero-based index of the type parameter * @return the generic type extends clause, or a blank string if not generic or no extends, not null */ public String getTypeGenericExtends(int typeParamIndex) { return typeGenericExtends[typeParamIndex]; } /** * Gets the extends clause of the parameterisation of the bean, such as '{@code extends Foo}'. * @param typeParamIndex the zero-based index of the type parameter * @param typeParamNames the type parameter names * @return the generic type extends clause, or a blank string if not generic or no extends, not null */ public String getTypeGenericExtends(int typeParamIndex, String[] typeParamNames) { var genericClause = typeGenericExtends[typeParamIndex]; genericClause = genericClause.replace("<" + typeGenericName[typeParamIndex] + ">", "<" + typeParamNames[typeParamIndex] + ">"); for (var i = 0; i < typeGenericName.length; i++) { genericClause = genericClause.replace("<" + typeGenericName[i] + ">", "<" + typeParamNames[i] + ">"); genericClause = genericClause.replace(" extends " + typeGenericName[i] + ">", " extends " + typeParamNames[i] + ">"); genericClause = genericClause.replace(" super " + typeGenericName[i] + ">", " super " + typeParamNames[i] + ">"); } return genericClause; } /** * Gets the full type of the bean with simple parameterization, such as '{@code Foo}'. * @return the generic type extends clause, or a blank string if not generic or no extends, not null */ public String getTypeNoExtends() { return typeRaw + getTypeGenericName(true); } /** * Gets the raw type of the bean without generics, such as '{@code Foo}'. * @return the raw type, not null */ public String getTypeRaw() { return typeRaw; } /** * Gets the full type of the bean with wildcarded parameterization, such as '{@code Foo}'. * @return the wildcarded type, not null */ public String getTypeWildcard() { if (!isTypeGeneric()) { return typeRaw; } var result = "?"; if (typeGenericExtends.length > 1) { result += ", ?"; if (typeGenericExtends.length > 2) { result += ", ?"; } } return typeRaw + '<' + result + '>'; } /** * Checks if the type specified is one of the bean's type parameters. * @param type the type * @return true if a type parameter of this bean */ public boolean isTypeGenerifiedBy(String type) { if ((typeGenericName.length > 2 && typeGenericName[2].equals(type)) || (typeGenericName.length > 1 && typeGenericName[1].equals(type))) { return true; } if (typeGenericName.length > 0 && typeGenericName[0].equals(type)) { return true; } return false; } //----------------------------------------------------------------------- /** * Checks if the super bean is parameterised with generics. * @return true if generified */ public boolean isSuperTypeGeneric() { return !superTypeGeneric.isEmpty(); } /** * Gets the bean superclass type. * @return the superclass */ public String getSuperType() { return superTypeFull; } /** * Gets the parameterisation of the super bean. * @param includeBrackets whether to include the brackets * @return the generic type, or a blank string if not generic, not null */ public String getSuperTypeGeneric(boolean includeBrackets) { return includeBrackets && !superTypeGeneric.isEmpty() ? '<' + superTypeGeneric + '>' : superTypeGeneric; } /** * Gets the raw type of the super bean without generics. * @return the raw type, not null */ public String getSuperTypeRaw() { return superTypeRaw; } /** * Checks if any property is validated. * @return true if validated */ public boolean isValidated() { return properties.stream().anyMatch(PropertyData::isValidated); } /** * Gets the scope of nested Meta and Builder classes. * @return the scope, not null */ public String getNestedClassConstructorScope() { return (isTypeFinal() ? "private" : "protected"); } } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanDefinition.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining a bean for code generation. *

* This annotation must be used on classes that should be treated as beans. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface BeanDefinition { /** * The style of bean generation. *

* By default, this follows 'smart' rules. * Set to 'minimal' to generate a minimal amount of code. * Set to 'full' to generate the full code. * Set to 'light' to generate a light immutable bean using reflection internally. * * @return the style, defaulted to 'smart' */ String style() default "smart"; /** * The scope of the generated constructor. *

* Only applicable to immutable beans. By default, this follows 'smart' * rules, which generate a private constructor when needed by the builder. * Set to 'private' to generate a private constructor. * Set to 'package' to generate a package-scoped constructor. * Set to 'protected' to generate a protected constructor. * Set to 'public' to generate a public constructor. * Set to 'public@ConstructorProperties' to generate an annotated public constructor. * * @return the constructor scope, defaulted to 'smart' */ String constructorScope() default "smart"; /** * The scope of the meta-bean class. *

* By default, this follows 'smart' rules, which generate a public meta-bean. * Set to 'private' to generate a private meta-bean. * Set to 'package' to generate a package-scoped meta-bean. * Set to 'public' to generate a public meta-bean. * * @return the meta scope, defaulted to 'smart' */ String metaScope() default "smart"; /** * The interfaces to add to the meta-bean class declaration. *

* By default, this adds no interfaces to the implements clause. * This option is only useful if the meta bean is a generated class. * * @return the meta scope, defaulted to '' */ String metaImplements() default ""; /** * The scope of the builder class. *

* By default, this follows 'smart' rules, which generate a public builder for * immutable beans and no builder for mutable beans. * Set to 'private' to generate a private builder. * Set to 'package' to generate a package-scoped builder. * Set to 'public' to generate a public builder. * * @return the builder scope, defaulted to 'smart' */ String builderScope() default "smart"; /** * The name of the manual builder class. *

* This is used when there is a desire to manually write the builder. * By default, this is not set, and a builder is generated based on the scope. * Set to 'FooBuilder' to generate code that expects a manually written builder named FooBuilder * (which may be an inner class or a top-level class). * * @return the builder scope, defaulted to '' */ String builderName() default ""; /** * The name of the factory method. *

* By default, this is an empty string and no factory is generated. * Set to 'of' to generate a factory method named 'of'. * * @return the factory name, defaulted to '' */ String factoryName() default ""; /** * Information about the bean hierarchy. *

* This is needed to add information that cannot be derived. * Set to 'immutable' for a subclass of an immutable bean. * * @return the hierarchy, defaulted to '' */ String hierarchy() default ""; /** * The configuration for generating clone methods. *

* This flag controls generation of the {@code clone} method. * The default is 'smart'. *

* The valid values are: *

    *
  • 'omit' - omit the clone method *
  • 'smart' - process intelligently, generating it for mutable and not generating for immutable *
  • 'generate' - generate the clone method *
* * @return the clone style, defaulted to 'smart' */ String cloneStyle() default "smart"; /** * Whether to generate code to cache the hash code. *

* Setting this to true will cause the hash code to be cached using the racy single check idiom. * The setting only applies to immutable beans. * * @return true if the hash code is to be cached */ boolean cacheHashCode() default false; } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.io.File; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.impl.BasicBeanBuilder; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.impl.direct.DirectPrivateBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; import org.joda.beans.impl.light.LightMetaBean; /** * Code generator for a bean. */ class BeanGen { /** Constructor style for none. */ static final int CONSTRUCTOR_NONE = 0; /** Constructor style for builder-based. */ static final int CONSTRUCTOR_BY_BUILDER = 1; /** Constructor style for argument-based. */ static final int CONSTRUCTOR_BY_ARGS = 2; /** Class name - this avoids a Class.class reference to the java.desktop module. */ private static final String CLASS_CONSTRUCTOR_PROPERTIES = "java.beans.ConstructorProperties"; /** Class name - this avoids a Class.class reference to the java.desktop module. */ private static final String CLASS_PROPERTY_CHANGE_SUPPORT = "java.beans.PropertyChangeSupport"; /** Line separator. */ private static final String LINE_SEPARATOR = "\t//-----------------------------------------------------------------------"; /** Line separator. */ private static final String LINE_SEPARATOR_INDENTED = "\t\t//-----------------------------------------------------------------------"; /** Types with primitive equals. */ private static final Set PRIMITIVE_EQUALS = new HashSet<>(); static { PRIMITIVE_EQUALS.add("boolean"); PRIMITIVE_EQUALS.add("char"); PRIMITIVE_EQUALS.add("byte"); PRIMITIVE_EQUALS.add("short"); PRIMITIVE_EQUALS.add("int"); PRIMITIVE_EQUALS.add("long"); // not float or double, as Double.equals is not the same as double == } /** The content to process. */ private final File file; /** The content to process. */ private final List content; /** The config. */ private final BeanGenConfig config; /** The data model of the bean. */ private final BeanData data; /** The list of property generators. */ private final List properties; /** The region to insert into. */ private final List insertRegion; /** The list of removed imports. */ private final SortedSet removedImports = new TreeSet<>(); /** * Constructor used when file is not a bean. * @param file the file, not null * @param content the content to process, not null * @param config the config to use, not null * @param data the parsed data */ BeanGen(File file, List content, BeanGenConfig config, BeanData data) { this.file = file; this.content = content; this.config = config; this.data = data; this.properties = null; this.insertRegion = null; } /** * Constructor used when file is a parsed bean. * @param file the file, not null * @param content the content to process, not null * @param config the config to use, not null * @param data the parsed data * @param properties the parsed properties * @param autoEndIndex the start of the autogen area * @param autoStartIndex the end of the autogen area */ BeanGen( File file, List content, BeanGenConfig config, BeanData data, List properties, int autoStartIndex, int autoEndIndex) { this.file = file; this.content = content; this.config = config; this.data = data; this.properties = properties; this.insertRegion = content.subList(autoStartIndex + 1, autoEndIndex); } //----------------------------------------------------------------------- void process() { fixImports(); if (insertRegion != null) { data.ensureImport(BeanDefinition.class); if (!properties.isEmpty()) { data.ensureImport(PropertyDefinition.class); } removeOld(); if (data.isRootClass() && data.isExtendsDirectBean()) { data.ensureImport(DirectBean.class); } generateMeta(); generateSerializationVersionId(); generatePropertyChangeSupportField(); generateHashCodeField(); generateFactory(); generateImmutableBuilderMethod(); generateArgBasedConstructor(); generateBuilderBasedConstructor(); generateMetaBean(); generateGettersSetters(); generateSeparator(); generateImmutableToBuilder(); generateClone(); generateEquals(); generateHashCode(); generateToString(); generateMetaClass(); generateBuilderClass(); resolveImports(); resolveIndents(); } } void processNonBean() { fixImports(); resolveImports(); } private void fixImports() { renameImport("org.joda.beans.BeanDefinition", BeanDefinition.class); renameImport("org.joda.beans.DerivedProperty", DerivedProperty.class); renameImport("org.joda.beans.ImmutableConstructor", ImmutableConstructor.class); renameImport("org.joda.beans.ImmutableDefaults", ImmutableDefaults.class); renameImport("org.joda.beans.ImmutablePreBuild", ImmutablePreBuild.class); renameImport("org.joda.beans.ImmutableValidator", ImmutableValidator.class); renameImport("org.joda.beans.PropertyDefinition", PropertyDefinition.class); } private void renameImport(String old, Class cls) { if (data.getCurrentImports().contains(old)) { removedImports.add(old); data.ensureImport(cls); } } private void resolveImports() { if (!data.getNewImports().isEmpty()) { var pos = data.getImportInsertLocation() + 1; for (var imp : data.getNewImports()) { content.add(pos++, "import " + imp + ";"); } } if (!removedImports.isEmpty()) { for (var it = content.listIterator(); it.hasNext(); ) { var line = it.next().trim(); if (line.startsWith("import ")) { var imported = line.substring(7).trim().replace(" ", "").replace(";", ""); if (removedImports.contains(imported)) { it.remove(); } } } } } private void resolveIndents() { for (var it = content.listIterator(); it.hasNext(); ) { it.set(it.next().replace("\t", config.getIndent())); } } private void removeOld() { insertRegion.clear(); } //----------------------------------------------------------------------- private void generateSeparator() { if (!insertRegion.isEmpty() && insertRegion.get(insertRegion.size() - 1).equals(LINE_SEPARATOR)) { return; } addLine(0, LINE_SEPARATOR); } private void generateIndentedSeparator() { if (!insertRegion.isEmpty() && insertRegion.get(insertRegion.size() - 1).equals(LINE_SEPARATOR_INDENTED)) { return; } addLine(0, LINE_SEPARATOR_INDENTED); } private void generateGenerated(int tabCount) { if (config.isGeneratedAnno()) { addLine(tabCount, "@Generated(\"org.joda.beans.gen.BeanCodeGen\")"); } } private void generateFactory() { if (data.isFactoryRequired()) { var nonDerived = nonDerivedProperties(); addLine(1, "/**"); addLine(1, " * Obtains an instance."); if (!nonDerived.isEmpty()) { if (data.isTypeGeneric()) { for (var j = 0; j < data.getTypeGenericCount(); j++) { addLine(1, " * @param " + data.getTypeGenericName(j, true) + " the type"); } } for (var propertyGen : nonDerived) { var prop = propertyGen.getData(); addLine(1, " * @param " + prop.getPropertyName() + " the value of the property" + prop.getNotNullJavadoc()); } } addLine(1, " * @return the instance"); addLine(1, " */"); if (nonDerived.isEmpty()) { addLine(1, "public static " + data.getTypeNoExtends() + " " + data.getFactoryName() + "() {"); addLine(2, "return new " + data.getTypeNoExtends() + "();"); } else { if (data.isTypeGeneric()) { addLine(1, "public static " + data.getTypeGeneric(true) + " " + data.getTypeNoExtends() + " " + data.getFactoryName() + "("); } else { addLine(1, "public static " + data.getTypeNoExtends() + " " + data.getFactoryName() + "("); } for (var i = 0; i < nonDerived.size(); i++) { var prop = nonDerived.get(i); addLine(3, prop.getBuilderType() + " " + prop.getData().getPropertyName() + joinComma(i, nonDerived, ") {")); } addLine(2, "return new " + data.getTypeWithDiamond() + "("); for (var i = 0; i < nonDerived.size(); i++) { addLine(3, nonDerived.get(i).generateBuilderFieldName() + joinComma(i, nonDerived, ");")); } } addLine(1, "}"); addBlankLine(); } } private void generateImmutableBuilderMethod() { if (data.isConstructable() && data.isBuilderGenerated()) { addLine(1, "/**"); addLine(1, " * Returns a builder used to create an instance of the bean."); if (data.isTypeGeneric()) { for (var j = 0; j < data.getTypeGenericCount(); j++) { addLine(1, " * @param " + data.getTypeGenericName(j, true) + " the type"); } } addLine(1, " * @return the builder, not null"); addLine(1, " */"); if (data.isTypeGeneric()) { addLine(1, data.getEffectiveBuilderScope() + "static " + data.getTypeGeneric(true) + " " + data.getEffectiveBeanBuilderName() + data.getTypeGenericName(true) + " builder() {"); } else { addLine(1, data.getEffectiveBuilderScope() + "static " + data.getEffectiveBeanBuilderName() + " builder() {"); } addLine(2, "return new " + data.getEffectiveBeanBuilderName() + data.getTypeGenericDiamond() + "();"); addLine(1, "}"); addBlankLine(); } } private void generateBuilderBasedConstructor() { if (data.getConstructorStyle() == CONSTRUCTOR_BY_BUILDER && data.getImmutableConstructor() == CONSTRUCTOR_NONE && ((data.isMutable() && data.isBuilderScopeVisible()) || data.isImmutable())) { var nonDerived = nonDerivedProperties(); var scope = (data.isTypeFinal() ? "private" : "protected"); // signature addLine(1, "/**"); addLine(1, " * Restricted constructor."); addLine(1, " * @param builder the builder to copy from, not null"); addLine(1, " */"); addLine(1, scope + " " + data.getTypeRaw() + "(" + data.getEffectiveBeanBuilderName() + data.getTypeGenericName(true) + " builder) {"); // super if (data.isSubClass()) { addLine(2, "super(builder);"); } // validate for (var prop : properties) { if (prop.getData().isValidated()) { addLine(2, prop.getData().getValidationMethodName() + "(builder." + prop.generateBuilderFieldName() + ", \"" + prop.getData().getPropertyName() + "\");"); } } // assign if (data.isImmutable()) { // assign for (var propertyGen : nonDerived) { addLines(propertyGen.generateConstructorAssign("builder.")); } } else { for (var propGen : nonDerived) { var prop = propGen.getData(); if (prop.isCollectionType()) { if (prop.isNotNull()) { addLine(2, "this." + prop.getPropertyName() + ".addAll(builder." + propGen.generateBuilderFieldName() + ");"); } else { addLine(2, "this." + prop.getPropertyName() + " = builder." + propGen.generateBuilderFieldName() + ";"); } } else if (prop.isMapType()) { if (prop.isNotNull()) { addLine(2, "this." + prop.getPropertyName() + ".putAll(builder." + propGen.generateBuilderFieldName() + ");"); } else { addLine(2, "this." + prop.getPropertyName() + " = builder." + propGen.generateBuilderFieldName() + ";"); } } else { addLine(2, "this." + prop.getPropertyName() + " = builder." + propGen.generateBuilderFieldName() + ";"); } } } if (data.getImmutableValidator() != null) { addLine(2, data.getImmutableValidator() + "();"); } addLine(1, "}"); addBlankLine(); } } private void generateArgBasedConstructor() { if (isArgBasedConstructor()) { var scope = data.getEffectiveConstructorScope(); var generateAnnotation = data.isConstructorPropertiesAnnotation(); var generateJavadoc = !"private ".equals(scope); var nonDerived = nonDerivedProperties(); if (nonDerived.isEmpty()) { if (generateJavadoc) { addLine(1, "/**"); addLine(1, " * Creates an instance."); addLine(1, " */"); } if (generateAnnotation) { data.ensureImport(CLASS_CONSTRUCTOR_PROPERTIES); addLine(1, "@ConstructorProperties({})"); } addLine(1, scope + data.getTypeRaw() + "() {"); } else { // signature if (generateJavadoc) { addLine(1, "/**"); addLine(1, " * Creates an instance."); for (var propertyGen : nonDerived) { var prop = propertyGen.getData(); addLine(1, " * @param " + prop.getPropertyName() + " the value of the property" + prop.getNotNullJavadoc()); } addLine(1, " */"); } if (generateAnnotation) { data.ensureImport(CLASS_CONSTRUCTOR_PROPERTIES); var buf = new StringBuilder(); for (var i = 0; i < nonDerived.size(); i++) { buf.append('"').append(nonDerived.get(i).getData().getPropertyName()).append('"'); buf.append(join(i, nonDerived, ", ", "")); } addLine(1, "@ConstructorProperties({" + buf + "})"); } addLine(1, scope + data.getTypeRaw() + "("); for (var i = 0; i < nonDerived.size(); i++) { var prop = nonDerived.get(i); addLine(3, prop.getBuilderType() + " " + prop.getData().getPropertyName() + joinComma(i, nonDerived, ") {")); } // validate (mutable light beans call setters which validate) if (!(data.isMutable() && data.isBeanStyleLight())) { for (var prop : properties) { if (prop.getData().isValidated()) { addLine(2, prop.getData().getValidationMethodName() + "(" + prop.getData().getPropertyName() + ", \"" + prop.getData().getPropertyName() + "\");"); } } } // assign for (var prop : nonDerived) { if (data.isMutable() && data.isBeanStyleLight()) { var generateSetInvoke = prop.getData().getSetterGen().generateSetInvoke( prop.getData(), prop.getData().getPropertyName()); addLine(2, generateSetInvoke + ";"); } else { addLines(prop.generateConstructorAssign("")); } } } if (data.getImmutableValidator() != null) { addLine(2, data.getImmutableValidator() + "();"); } addLine(1, "}"); addBlankLine(); } } private boolean isArgBasedConstructor() { if (data.getConstructorStyle() == CONSTRUCTOR_BY_ARGS && data.getImmutableConstructor() == CONSTRUCTOR_NONE && ((data.isMutable() && (data.isBuilderScopeVisible() || data.isBeanStyleLight())) || data.isImmutable())) { return true; } return data.getConstructorStyle() == CONSTRUCTOR_BY_BUILDER && data.getImmutableConstructor() == CONSTRUCTOR_NONE && data.isImmutable() && !data.isTypeFinal() && !"smart".equals(data.getConstructorScope()); } //----------------------------------------------------------------------- private void generateMeta() { if (data.isBeanStyleLightOrMinimal()) { addLine(1, "/**"); addLine(1, " * The meta-bean for {@code " + data.getTypeRaw() + "}."); addLine(1, " */"); var genericProps = data.getProperties().stream() .anyMatch(p -> p.isGeneric()); var unchecked = data.isBeanStyleMinimal() && data.isMutable() && genericProps; unchecked |= data.isBeanStyleMinimal() && data.isTypeGeneric() && !data.isSkipBuilderGeneration(); var rawtypes = data.isBeanStyleMinimal() && data.isTypeGeneric(); if (unchecked && rawtypes) { addLine(1, "@SuppressWarnings({\"unchecked\", \"rawtypes\" })"); } else if (rawtypes) { addLine(1, "@SuppressWarnings(\"rawtypes\")"); } else if (unchecked) { addLine(1, "@SuppressWarnings(\"unchecked\")"); } if (data.isTypeGeneric()) { data.ensureImport(MetaBean.class); addLine(1, "private static final MetaBean META_BEAN ="); } else { data.ensureImport(TypedMetaBean.class); addLine(1, "private static final TypedMetaBean<" + data.getTypeNoExtends() + "> META_BEAN ="); } var nonDerived = nonDerivedProperties(); var aliases = nonDerived.stream().filter(p -> p.getData().getAlias() != null).toList(); var hasAliases = aliases.isEmpty(); if (data.isBeanStyleLight()) { // light data.ensureImport(LightMetaBean.class); data.ensureImport(MethodHandles.class); var specialInit = nonDerived.stream().anyMatch(p -> p.isSpecialInit()); if (nonDerived.isEmpty()) { addLine(3, "LightMetaBean.of(" + data.getTypeRaw() + ".class, MethodHandles.lookup());"); } else { addLine(3, "LightMetaBean.of("); addLine(5, data.getTypeRaw() + ".class,"); addLine(5, "MethodHandles.lookup(),"); generateFieldNames(nonDerived); if (specialInit) { for (var i = 0; i < nonDerived.size(); i++) { addLine(5, nonDerived.get(i).generateInit() + joinComma(i, nonDerived, ")" + (hasAliases ? ";" : ""))); } } else { addLine(5, "new Object[0])" + (hasAliases ? ";" : "")); } for (var i = 0; i < aliases.size(); i++) { var prop = aliases.get(i); addLine(5, ".withAlias(\"" + prop.getData().getAlias() + "\", \"" + prop.getData().getPropertyName() + "\")" + join(i, aliases, "", ";")); } } } else { // minimal data.ensureImport(MinimalMetaBean.class); addLine(3, "MinimalMetaBean.of("); addLine(5, data.getTypeRaw() + ".class,"); generateFieldNames(nonDerived); var builderLambda = "() -> new " + data.getEffectiveBeanBuilderName() + "()"; if (data.isSkipBuilderGeneration()) { if (data.isBeanBuilderManual()) { builderLambda = "() -> new " + data.getEffectiveMinimalBeanBuilderName() + "()"; } else { data.ensureImport(BasicBeanBuilder.class); builderLambda = "() -> new BasicBeanBuilder<>(new " + data.getTypeWithDiamond() + "())"; } } if (nonDerived.isEmpty()) { if (data.isImmutable()) { addLine(5, builderLambda + ");"); } else { data.ensureImport(Collections.class); data.ensureImport(Function.class); data.ensureImport(BiConsumer.class); addLine(5, builderLambda + ","); addLine(5, "Collections.>emptyList(),"); addLine(5, "Collections.>emptyList());"); } } else { addLine(5, builderLambda + ","); if (data.isImmutable()) { for (var i = 0; i < nonDerived.size(); i++) { addLine(5, nonDerived.get(i).generateLambdaGetter() + joinComma(i, nonDerived, ")" + (hasAliases ? ";" : ""))); } } else { data.ensureImport(Arrays.class); data.ensureImport(Function.class); data.ensureImport(BiConsumer.class); addLine(5, "Arrays.>asList("); for (var i = 0; i < nonDerived.size(); i++) { addLine(7, nonDerived.get(i).generateLambdaGetter() + joinComma(i, nonDerived, "),")); } addLine(5, "Arrays.>asList("); for (var i = 0; i < nonDerived.size(); i++) { addLine(7, nonDerived.get(i).generateLambdaSetter() + joinComma(i, nonDerived, "))" + (hasAliases ? ";" : ""))); } } for (var i = 0; i < aliases.size(); i++) { var prop = aliases.get(i); addLine(5, ".withAlias(\"" + prop.getData().getAlias() + "\", \"" + prop.getData().getPropertyName() + "\")" + join(i, aliases, "", ";")); } } } addBlankLine(); addLine(1, "/**"); addLine(1, " * The meta-bean for {@code " + data.getTypeRaw() + "}."); addLine(1, " * @return the meta-bean, not null"); addLine(1, " */"); if (data.isTypeGeneric()) { addLine(1, "public static MetaBean meta() {"); } else { addLine(1, "public static TypedMetaBean<" + data.getTypeNoExtends() + "> meta() {"); } addLine(2, "return META_BEAN;"); addLine(1, "}"); addBlankLine(); addLine(1, "static {"); data.ensureImport(MetaBean.class); addLine(2, "MetaBean.register(META_BEAN);"); addLine(1, "}"); addBlankLine(); } else { // this cannot be generified without either Eclipse or javac complaining // raw types forever addLine(1, "/**"); addLine(1, " * The meta-bean for {@code " + data.getTypeRaw() + "}."); addLine(1, " * @return the meta-bean, not null"); if (data.isMetaScopePrivate()) { data.ensureImport(MetaBean.class); addLine(1, " */"); addLine(1, "public static MetaBean meta() {"); } else if (data.isTypeGeneric()) { addLine(1, " */"); addLine(1, "@SuppressWarnings(\"rawtypes\")"); addLine(1, "public static " + data.getTypeRaw() + ".Meta meta() {"); } else { addLine(1, " */"); addLine(1, "public static " + data.getTypeRaw() + ".Meta meta() {"); } addLine(2, "return " + data.getTypeRaw() + ".Meta.INSTANCE;"); addLine(1, "}"); if (data.isTypeGeneric()) { generateMetaForGenericType(); } addBlankLine(); addLine(1, "static {"); data.ensureImport(MetaBean.class); addLine(2, "MetaBean.register(" + data.getTypeRaw() + ".Meta.INSTANCE);"); addLine(1, "}"); addBlankLine(); } } private void generateFieldNames(List nonDerived) { if (nonDerived.isEmpty()) { addLine(5, "new String[0],"); } else { addLine(5, "new String[] {"); for (var i = 0; i < nonDerived.size(); i++) { addLine(7, "\"" + nonDerived.get(i).getData().getFieldName() + join(i, nonDerived, "\",", "\"},")); } } } private void generateMetaForGenericType() { // this works around an Eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=397462 // long name needed for uniqueness as static overriding is borked addBlankLine(); addLine(1, "/**"); addLine(1, " * The meta-bean for {@code " + data.getTypeRaw() + "}."); if (data.getTypeGenericCount() == 1) { addLine(1, " * @param the bean's generic type"); addLine(1, " * @param cls the bean's generic type"); } else if (data.getTypeGenericCount() == 2) { addLine(1, " * @param the first generic type"); addLine(1, " * @param the second generic type"); addLine(1, " * @param cls1 the first generic type"); addLine(1, " * @param cls2 the second generic type"); } else if (data.getTypeGenericCount() == 3) { addLine(1, " * @param the first generic type"); addLine(1, " * @param the second generic type"); addLine(1, " * @param the second generic type"); addLine(1, " * @param cls1 the first generic type"); addLine(1, " * @param cls2 the second generic type"); addLine(1, " * @param cls3 the third generic type"); } addLine(1, " * @return the meta-bean, not null"); addLine(1, " */"); addLine(1, "@SuppressWarnings(\"unchecked\")"); var typeNames = new String[] {"R", "S", "T"}; if (data.getTypeGenericCount() == 1) { addLine(1, "public static " + data.getTypeRaw() + ".Meta meta" + data.getTypeRaw() + "(Class cls) {"); } else if (data.getTypeGenericCount() == 2) { addLine(1, "public static " + data.getTypeRaw() + ".Meta meta" + data.getTypeRaw() + "(Class cls1, Class cls2) {"); } else if (data.getTypeGenericCount() == 3) { addLine(1, "public static " + data.getTypeRaw() + ".Meta meta" + data.getTypeRaw() + "(Class cls1, Class cls2, Class cls3) {"); } addLine(2, "return " + data.getTypeRaw() + ".Meta.INSTANCE;"); addLine(1, "}"); } private void generateSerializationVersionId() { if (data.isSerializable() && !data.isManualSerializationId()) { addLine(1, "/**"); addLine(1, " * The serialization version id."); addLine(1, " */"); addLine(1, "private static final long serialVersionUID = 1L;"); addBlankLine(); } } private void generatePropertyChangeSupportField() { if (data.isPropertyChangeSupport()) { data.ensureImport(CLASS_PROPERTY_CHANGE_SUPPORT); addLine(1, "/**"); addLine(1, " * The property change support field."); addLine(1, " */"); addLine(1, "private final transient PropertyChangeSupport " + config.getPrefix() + "propertyChangeSupport = new PropertyChangeSupport(this);"); addBlankLine(); } } private void generateHashCodeField() { if (data.isCacheHashCode()) { addLine(1, "/**"); addLine(1, " * The cached hash code, using the racy single-check idiom."); addLine(1, " */"); addLine(1, "private transient int " + config.getPrefix() + "cacheHashCode;"); addBlankLine(); } } private void generateMetaBean() { if (data.isMetaScopePrivate() || data.isBeanStyleMinimal()) { addLine(1, "@Override"); if (data.isBeanStyleLightOrMinimal()) { data.ensureImport(TypedMetaBean.class); if (data.isTypeGeneric()) { addLine(1, "@SuppressWarnings(\"unchecked\")"); } addLine(1, "public TypedMetaBean<" + data.getTypeNoExtends() + "> metaBean() {"); if (data.isTypeGeneric()) { addLine(2, "return (TypedMetaBean<" + data.getTypeNoExtends() + ">) META_BEAN;"); } else { addLine(2, "return META_BEAN;"); } } else { data.ensureImport(MetaBean.class); addLine(1, "public MetaBean metaBean() {"); addLine(2, "return " + data.getTypeRaw() + ".Meta.INSTANCE;"); } addLine(1, "}"); addBlankLine(); } else { if (data.isTypeGeneric()) { addLine(1, "@SuppressWarnings(\"unchecked\")"); } addLine(1, "@Override"); addLine(1, "public " + data.getTypeRaw() + ".Meta" + data.getTypeGenericName(true) + " metaBean() {"); addLine(2, "return " + data.getTypeRaw() + ".Meta.INSTANCE;"); addLine(1, "}"); addBlankLine(); } } private void generateGettersSetters() { for (var prop : properties) { generateSeparator(); addLines(prop.generateGetter()); if (data.isMutable()) { addLines(prop.generateSetter()); } if (data.isBeanStyleGenerateProperties()) { addLines(prop.generateProperty()); } } } //----------------------------------------------------------------------- private void generateImmutableToBuilder() { if (data.isBuilderGenerated()) { if (data.isConstructable()) { var nonDerived = nonDerivedProperties(); if (!nonDerived.isEmpty() || !data.isTypeFinal()) { addLine(1, "/**"); addLine(1, " * Returns a builder that allows this bean to be mutated."); addLine(1, " * @return the mutable builder, not null"); addLine(1, " */"); if (!data.isRootClass()) { addLine(1, "@Override"); } addLine(1, data.getEffectiveBuilderScope() + data.getEffectiveMinimalBeanBuilderName() + data.getTypeGenericName(true) + " toBuilder() {"); addLine(2, "return new " + data.getEffectiveMinimalBeanBuilderName() + data.getTypeGenericDiamond() + "(this);"); addLine(1, "}"); addBlankLine(); } } else { addLine(1, "/**"); addLine(1, " * Returns a builder that allows this bean to be mutated."); addLine(1, " * @return the mutable builder, not null"); addLine(1, " */"); if (!data.isRootClass()) { addLine(1, "@Override"); } addLine(1, "public abstract " + data.getEffectiveMinimalBeanBuilderName() + data.getTypeGenericName(true) + " toBuilder();"); addBlankLine(); } } } private void generateClone() { if (data.isSkipCloneGeneration() || data.isManualClone() || (!data.isRootClass() && !data.isConstructable())) { return; } addLine(1, "@Override"); if (data.isImmutable()) { addLine(1, "public " + data.getTypeNoExtends() + " clone() {"); addLine(2, "return this;"); } else { data.ensureImport(JodaBeanUtils.class); addLine(1, "public " + data.getTypeNoExtends() + " clone() {"); addLine(2, "return JodaBeanUtils.cloneAlways(this);"); } addLine(1, "}"); addBlankLine(); } private void generateEquals() { if (data.isManualEqualsHashCode()) { return; } addLine(1, "@Override"); generateGenerated(1); addLine(1, "public boolean equals(Object obj) {"); addLine(2, "if (obj == this) {"); addLine(3, "return true;"); addLine(2, "}"); addLine(2, "if (obj != null && obj.getClass() == this.getClass()) {"); var nonDerived = nonDerivedEqualsHashCodeProperties(); if (nonDerived.isEmpty()) { if (data.isSubClass()) { addLine(3, "return super.equals(obj);"); } else { addLine(3, "return true;"); } } else { addLine(3, data.getTypeWildcard() + " other = (" + data.getTypeWildcard() + ") obj;"); for (var i = 0; i < nonDerived.size(); i++) { var prop = nonDerived.get(i); var getter = equalsHashCodeFieldAccessor(prop); data.ensureImport(JodaBeanUtils.class); var equals = "JodaBeanUtils.equal(this." + getter + ", other." + getter + ")"; if (PRIMITIVE_EQUALS.contains(prop.getData().getType())) { equals = "(this." + getter + " == other." + getter + ")"; } addLine( 0, (i == 0 ? "\t\t\treturn " : "\t\t\t\t\t") + equals + (data.isSubClass() || i < nonDerived.size() - 1 ? " &&" : ";")); } if (data.isSubClass()) { addLine(5, "super.equals(obj);"); } } addLine(2, "}"); addLine(2, "return false;"); addLine(1, "}"); addBlankLine(); } private void generateHashCode() { if (data.isManualEqualsHashCode()) { return; } addLine(1, "@Override"); generateGenerated(1); addLine(1, "public int hashCode() {"); if (data.isCacheHashCode()) { addLine(2, "int hash = " + config.getPrefix() + "cacheHashCode;"); addLine(2, "if (hash == 0) {"); if (data.isSubClass()) { addLine(3, "hash = 7;"); } else { addLine(3, "hash = getClass().hashCode();"); } generateHashCodeContent("\t\t\t"); if (data.isSubClass()) { addLine(3, "hash = hash ^ super.hashCode();"); } addLine(3, config.getPrefix() + "cacheHashCode = hash;"); addLine(2, "}"); addLine(2, "return hash;"); } else { if (data.isSubClass()) { addLine(2, "int hash = 7;"); } else { addLine(2, "int hash = getClass().hashCode();"); } generateHashCodeContent("\t\t"); if (data.isSubClass()) { addLine(2, "return hash ^ super.hashCode();"); } else { addLine(2, "return hash;"); } } addLine(1, "}"); addBlankLine(); } private void generateHashCodeContent(String indent) { var nonDerived = nonDerivedEqualsHashCodeProperties(); for (var prop : nonDerived) { var getter = equalsHashCodeFieldAccessor(prop); data.ensureImport(JodaBeanUtils.class); addLine(0, indent + "hash = hash * 31 + JodaBeanUtils.hashCode(" + getter + ");"); } } private String equalsHashCodeFieldAccessor(PropertyGen prop) { if (prop.getData().getEqualsHashCodeStyle().equals("field")) { return prop.getData().getFieldName(); } else { return prop.getData().getGetterGen().generateGetInvoke(prop.getData()); } } private void generateToString() { if (data.isManualToStringCode()) { return; } var props = toStringProperties(); if (data.isRootClass() && data.isTypeFinal()) { addLine(1, "@Override"); generateGenerated(1); addLine(1, "public String toString() {"); addLine(2, "StringBuilder buf = new StringBuilder(" + (props.size() * 32 + 32) + ");"); addLine(2, "buf.append(\"" + data.getTypeRaw() + "{\");"); if (!props.isEmpty()) { data.ensureImport(JodaBeanUtils.class); for (var i = 0; i < props.size(); i++) { var prop = props.get(i); var getter = toStringFieldAccessor(prop); addLine(2, "buf.append(\"" + prop.getData().getPropertyName() + "\").append('=')" + join(i, props, ".append(JodaBeanUtils.toString(" + getter + ")).append(',').append(' ');", ".append(JodaBeanUtils.toString(" + getter + "));")); } } addLine(2, "buf.append('}');"); addLine(2, "return buf.toString();"); addLine(1, "}"); addBlankLine(); return; } addLine(1, "@Override"); generateGenerated(1); addLine(1, "public String toString() {"); addLine(2, "StringBuilder buf = new StringBuilder(" + (props.size() * 32 + 32) + ");"); addLine(2, "buf.append(\"" + data.getTypeRaw() + "{\");"); addLine(2, "int len = buf.length();"); addLine(2, "toString(buf);"); addLine(2, "if (buf.length() > len) {"); addLine(3, "buf.setLength(buf.length() - 2);"); addLine(2, "}"); addLine(2, "buf.append('}');"); addLine(2, "return buf.toString();"); addLine(1, "}"); addBlankLine(); if (data.isSubClass()) { addLine(1, "@Override"); } generateGenerated(1); addLine(1, "protected void toString(StringBuilder buf) {"); if (data.isSubClass()) { addLine(2, "super.toString(buf);"); } for (var prop : props) { var getter = toStringFieldAccessor(prop); data.ensureImport(JodaBeanUtils.class); addLine(2, "buf.append(\"" + prop.getData().getPropertyName() + "\").append('=').append(JodaBeanUtils.toString(" + getter + ")).append(',').append(' ');"); } addLine(1, "}"); addBlankLine(); } private String toStringFieldAccessor(PropertyGen prop) { if (prop.getData().isDerived()) { return prop.getData().getGetterGen().generateGetInvoke(prop.getData()); } else if (prop.getData().getToStringStyle().equals("field")) { return prop.getData().getFieldName(); } else { return prop.getData().getGetterGen().generateGetInvoke(prop.getData()); } } //----------------------------------------------------------------------- private void generateMetaClass() { if (data.isBeanStyleLightOrMinimal()) { return; } generateSeparator(); addLine(1, "/**"); addLine(1, " * The meta-bean for {@code " + data.getTypeRaw() + "}."); if (data.isTypeGeneric()) { for (var j = 0; j < data.getTypeGenericCount(); j++) { addLine(1, " * @param " + data.getTypeGenericName(j, true) + " the type"); } } addLine(1, " */"); generateGenerated(1); String superMeta; if (data.isSubClass()) { superMeta = data.getSuperTypeRaw() + ".Meta" + data.getSuperTypeGeneric(true); } else { data.ensureImport(DirectMetaBean.class); superMeta = "DirectMetaBean"; } var finalType = data.isTypeFinal() ? "final " : ""; var implementClause = data.getBeanMetaImplements().isEmpty() ? "" : " implements " + data.getBeanMetaImplements(); if (data.isTypeGeneric()) { addLine(1, data.getEffectiveMetaScope() + "static " + finalType + "class Meta" + data.getTypeGeneric(true) + " extends " + superMeta + implementClause + " {"); } else { addLine(1, data.getEffectiveMetaScope() + "static " + finalType + "class Meta extends " + superMeta + implementClause + " {"); } addLine(2, "/**"); addLine(2, " * The singleton instance of the meta-bean."); addLine(2, " */"); if (data.isTypeGeneric()) { addLine(2, "@SuppressWarnings(\"rawtypes\")"); } addLine(2, "static final Meta INSTANCE = new Meta();"); addBlankLine(); generateMetaPropertyConstants(); generateMetaPropertyMapSetup(); addLine(2, "/**"); addLine(2, " * Restricted constructor."); addLine(2, " */"); addLine(2, data.getNestedClassConstructorScope() + " Meta() {"); addLine(2, "}"); addBlankLine(); generateMetaPropertyGet(); generateMetaBuilder(); generateMetaBeanType(); generateMetaPropertyMap(); generateIndentedSeparator(); generateMetaPropertyMethods(); generateIndentedSeparator(); generateMetaGetPropertyValue(); generateMetaSetPropertyValue(); generateMetaValidate(); addLine(1, "}"); addBlankLine(); } private void generateMetaPropertyConstants() { for (var prop : properties) { addLines(prop.generateMetaPropertyConstant()); } } private void generateMetaPropertyMapSetup() { data.ensureImport(MetaProperty.class); data.ensureImport(DirectMetaPropertyMap.class); addLine(2, "/**"); addLine(2, " * The meta-properties."); addLine(2, " */"); addLine(2, "private final Map> " + config.getPrefix() + "metaPropertyMap$ = new DirectMetaPropertyMap("); if (data.isSubClass()) { addLine(4, "this, (DirectMetaPropertyMap) super.metaPropertyMap()" + (properties.isEmpty() ? ");" : ",")); } else { addLine(4, "this, null" + (properties.isEmpty() ? ");" : ",")); } for (var i = 0; i < properties.size(); i++) { addLine(4, "\"" + properties.get(i).getData().getPropertyName() + "\"" + joinComma(i, properties, ");")); } addBlankLine(); } private void generateMetaBuilder() { if (!data.isConstructable()) { addLine(2, "@Override"); addLine(2, "public boolean isBuildable() {"); addLine(3, "return false;"); addLine(2, "}"); addBlankLine(); } addLine(2, "@Override"); if (data.isImmutable() && !data.isEffectiveBuilderScopeVisible()) { data.ensureImport(BeanBuilder.class); addLine(2, "public BeanBuilder builder() {"); if (data.isConstructable()) { addLine(3, "return new " + data.getEffectiveBeanBuilderName() + data.getTypeGenericDiamond() + "();"); } else { addLine(3, "throw new UnsupportedOperationException(\"" + data.getTypeRaw() + " is an abstract class\");"); } } else if (data.isImmutable() || (data.isMutable() && data.isBuilderScopeVisible())) { addLine(2, "public " + data.getEffectiveBeanBuilderName() + data.getTypeGenericName(true) + " builder() {"); if (data.isConstructable()) { addLine(3, "return new " + data.getEffectiveBeanBuilderName() + data.getTypeGenericDiamond() + "();"); } else { addLine(3, "throw new UnsupportedOperationException(\"" + data.getTypeRaw() + " is an abstract class\");"); } } else { data.ensureImport(BeanBuilder.class); addLine(2, "public BeanBuilder builder() {"); if (data.isConstructable()) { data.ensureImport(DirectBeanBuilder.class); addLine(3, "return new DirectBeanBuilder<>(new " + data.getTypeNoExtends() + "());"); } else { addLine(3, "throw new UnsupportedOperationException(\"" + data.getTypeRaw() + " is an abstract class\");"); } } addLine(2, "}"); addBlankLine(); } private void generateMetaBeanType() { if (data.isTypeGeneric()) { addLine(2, "@SuppressWarnings({\"unchecked\", \"rawtypes\" })"); } addLine(2, "@Override"); addLine(2, "public Class beanType() {"); if (data.isTypeGeneric()) { addLine(3, "return (Class) " + data.getTypeRaw() + ".class;"); } else { addLine(3, "return " + data.getTypeNoExtends() + ".class;"); } addLine(2, "}"); addBlankLine(); } private void generateMetaPropertyGet() { if (!properties.isEmpty()) { data.ensureImport(MetaProperty.class); addLine(2, "@Override"); addLine(2, "protected MetaProperty metaPropertyGet(String propertyName) {"); addLine(3, "switch (propertyName.hashCode()) {"); for (var prop : properties) { addLines(prop.generateMetaPropertyGetCase()); } addLine(3, "}"); addLine(3, "return super.metaPropertyGet(propertyName);"); addLine(2, "}"); addBlankLine(); } } private void generateMetaPropertyMap() { data.ensureImport(Map.class); addLine(2, "@Override"); addLine(2, "public Map> metaPropertyMap() {"); addLine(3, "return " + config.getPrefix() + "metaPropertyMap$;"); addLine(2, "}"); addBlankLine(); } private void generateMetaPropertyMethods() { if (data.isBeanStyleGenerateMetaProperties()) { for (var prop : properties) { addLines(prop.generateMetaProperty()); } } } //----------------------------------------------------------------------- private void generateMetaGetPropertyValue() { if (properties.isEmpty()) { return; } data.ensureImport(Bean.class); addLine(2, "@Override"); addLine(2, "protected Object propertyGet(Bean bean, String propertyName, boolean quiet) {"); addLine(3, "switch (propertyName.hashCode()) {"); for (var prop : properties) { addLines(prop.generatePropertyGetCase()); } addLine(3, "}"); addLine(3, "return super.propertyGet(bean, propertyName, quiet);"); addLine(2, "}"); addBlankLine(); } private void generateMetaSetPropertyValue() { if (properties.isEmpty()) { return; } data.ensureImport(Bean.class); if (data.isImmutable()) { addLine(2, "@Override"); addLine(2, "protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) {"); addLine(3, "metaProperty(propertyName);"); addLine(3, "if (quiet) {"); addLine(4, "return;"); addLine(3, "}"); addLine(3, "throw new UnsupportedOperationException(\"Property cannot be written: \" + propertyName);"); addLine(2, "}"); addBlankLine(); return; } var generics = false; for (var prop : data.getProperties()) { generics |= (prop.getStyle().isWritable() && ((prop.isGeneric() && !prop.isGenericWildcardParamType()) || data.isTypeGeneric())); } if (generics) { addLine(2, "@SuppressWarnings(\"unchecked\")"); } addLine(2, "@Override"); addLine(2, "protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) {"); addLine(3, "switch (propertyName.hashCode()) {"); for (var prop : properties) { addLines(prop.generatePropertySetCase()); } addLine(3, "}"); addLine(3, "super.propertySet(bean, propertyName, newValue, quiet);"); addLine(2, "}"); addBlankLine(); } private void generateMetaValidate() { if (!data.isValidated() || data.isImmutable()) { return; } data.ensureImport(Bean.class); addLine(2, "@Override"); addLine(2, "protected void validate(Bean bean) {"); if (data.isValidated()) { for (var prop : properties) { if (prop.getData().isValidated()) { addLine(3, prop.getData().getValidationMethodName() + "(((" + data.getTypeWildcard() + ") bean)." + prop.getData().getFieldName() + ", \"" + prop.getData().getPropertyName() + "\");"); } } } if (data.isSubClass()) { addLine(3, "super.validate(bean);"); } addLine(2, "}"); addBlankLine(); } //----------------------------------------------------------------------- private void generateBuilderClass() { if (data.isSkipBuilderGeneration()) { return; } var nonDerived = nonDerivedProperties(); generateSeparator(); var finalType = data.isTypeFinal() ? "final " : ""; addLine(1, "/**"); addLine(1, " * The bean-builder for {@code " + data.getTypeRaw() + "}."); if (data.isTypeGeneric()) { for (var j = 0; j < data.getTypeGenericCount(); j++) { addLine(1, " * @param " + data.getTypeGenericName(j, true) + " the type"); } } addLine(1, " */"); generateGenerated(1); String superBuilder; if (data.isSubClass()) { superBuilder = data.getSuperTypeRaw() + ".Builder" + data.getSuperTypeGeneric(true); } else if (data.isEffectiveBuilderScopeVisible()) { data.ensureImport(DirectFieldsBeanBuilder.class); superBuilder = "DirectFieldsBeanBuilder<" + data.getTypeNoExtends() + ">"; } else { data.ensureImport(DirectPrivateBeanBuilder.class); superBuilder = "DirectPrivateBeanBuilder<" + data.getTypeNoExtends() + ">"; } if (data.isConstructable()) { addLine(1, data.getEffectiveBuilderScope() + "static " + finalType + "class Builder" + data.getTypeGeneric(true) + " extends " + superBuilder + " {"); } else { addLine(1, data.getEffectiveBuilderScope() + "abstract static " + finalType + "class Builder" + data.getTypeGeneric(true) + " extends " + superBuilder + " {"); } if (!nonDerived.isEmpty()) { addBlankLine(); generateBuilderProperties(); } addBlankLine(); generateBuilderConstructorNoArgs(); generateBuilderConstructorCopy(); generateIndentedSeparator(); generateBuilderGet(); generateBuilderSet(); generateBuilderOtherSets(); if (data.isConstructable()) { generateBuilderBuild(); } generateIndentedSeparator(); generateBuilderPropertySetMethods(); generateIndentedSeparator(); generateBuilderToString(); addLine(1, "}"); addBlankLine(); } private void generateBuilderConstructorNoArgs() { addLine(2, "/**"); addLine(2, " * Restricted constructor."); addLine(2, " */"); addLine(2, data.getNestedClassConstructorScope() + " Builder() {"); if (data.getImmutableDefaults() != null) { addLine(3, data.getImmutableDefaults() + "(this);"); } addLine(2, "}"); addBlankLine(); } private void generateBuilderConstructorCopy() { if (data.isBuilderGenerated()) { var nonDerived = nonDerivedProperties(); if (!nonDerived.isEmpty() || !data.isTypeFinal()) { addLine(2, "/**"); addLine(2, " * Restricted copy constructor."); addLine(2, " * @param beanToCopy the bean to copy from, not null"); addLine(2, " */"); addLine(2, data.getNestedClassConstructorScope() + " Builder(" + data.getTypeNoExtends() + " beanToCopy) {"); if (data.isSubClass()) { addLine(3, "super(beanToCopy);"); } for (var propertyGen : nonDerived) { addLines(propertyGen.generateBuilderConstructorAssign("beanToCopy")); } addLine(2, "}"); addBlankLine(); } } } private void generateBuilderProperties() { for (var prop : nonDerivedProperties()) { addLines(prop.generateBuilderField()); } } private void generateBuilderGet() { var nonDerived = nonDerivedProperties(); addLine(2, "@Override"); addLine(2, "public Object get(String propertyName) {"); if (!nonDerived.isEmpty()) { addLine(3, "switch (propertyName.hashCode()) {"); for (var prop : nonDerived) { addLines(prop.generateBuilderFieldGet()); } addLine(4, "default:"); if (data.isRootClass()) { data.ensureImport(NoSuchElementException.class); addLine(5, "throw new NoSuchElementException(\"Unknown property: \" + propertyName);"); } else { addLine(5, "return super.get(propertyName);"); } addLine(3, "}"); } else { if (!data.isRootClass()) { addLine(3, "return super.get(propertyName);"); } else { data.ensureImport(NoSuchElementException.class); addLine(3, "throw new NoSuchElementException(\"Unknown property: \" + propertyName);"); } } addLine(2, "}"); addBlankLine(); } private void generateBuilderSet() { var nonDerived = nonDerivedProperties(); var generics = data.getProperties().stream() .anyMatch(p -> p.isGeneric() && !p.isGenericWildcardParamType()); if (generics) { addLine(2, "@SuppressWarnings(\"unchecked\")"); } addLine(2, "@Override"); addLine(2, "public Builder" + data.getTypeGenericName(true) + " set(String propertyName, Object newValue) {"); if (!nonDerived.isEmpty()) { addLine(3, "switch (propertyName.hashCode()) {"); for (var prop : nonDerived) { addLines(prop.generateBuilderFieldSet()); } addLine(4, "default:"); if (data.isRootClass()) { data.ensureImport(NoSuchElementException.class); addLine(5, "throw new NoSuchElementException(\"Unknown property: \" + propertyName);"); } else { addLine(5, "super.set(propertyName, newValue);"); addLine(5, "break;"); } addLine(3, "}"); addLine(3, "return this;"); } else { if (!data.isRootClass()) { addLine(3, "super.set(propertyName, newValue);"); addLine(3, "return this;"); } else { data.ensureImport(NoSuchElementException.class); addLine(3, "throw new NoSuchElementException(\"Unknown property: \" + propertyName);"); } } addLine(2, "}"); addBlankLine(); } private void generateBuilderOtherSets() { if (data.isEffectiveBuilderScopeVisible()) { addLine(2, "@Override"); addLine(2, "public Builder" + data.getTypeGenericName(true) + " set(MetaProperty property, Object value) {"); addLine(3, "super.set(property, value);"); addLine(3, "return this;"); addLine(2, "}"); addBlankLine(); } } private void generateBuilderBuild() { var nonDerived = nonDerivedProperties(); addLine(2, "@Override"); addLine(2, "public " + data.getTypeRaw() + data.getTypeGenericName(true) + " build() {"); if (data.getImmutablePreBuild() != null) { addLine(3, data.getImmutablePreBuild() + "(this);"); } if (data.getConstructorStyle() == CONSTRUCTOR_BY_ARGS) { if (nonDerived.isEmpty()) { addLine(3, "return new " + data.getTypeWithDiamond() + "();"); } else { addLine(3, "return new " + data.getTypeWithDiamond() + "("); for (var i = 0; i < nonDerived.size(); i++) { addLine(5, nonDerived.get(i).generateBuilderFieldName() + joinComma(i, nonDerived, ");")); } } } else if (data.getConstructorStyle() == CONSTRUCTOR_BY_BUILDER) { addLine(3, "return new " + data.getTypeWithDiamond() + "(this);"); } addLine(2, "}"); addBlankLine(); } private void generateBuilderPropertySetMethods() { if (data.isEffectiveBuilderScopeVisible()) { for (var prop : nonDerivedProperties()) { addLines(prop.generateBuilderSetMethod()); } } } private void generateBuilderToString() { var nonDerived = toStringProperties(); if (data.isImmutable() && data.isTypeFinal()) { addLine(2, "@Override"); addLine(2, "public String toString() {"); if (nonDerived.isEmpty()) { addLine(3, "return \"" + data.getEffectiveBeanBuilderName() + "{}\";"); } else { addLine(3, "StringBuilder buf = new StringBuilder(" + (nonDerived.size() * 32 + 32) + ");"); addLine(3, "buf.append(\"" + data.getEffectiveBeanBuilderName() + "{\");"); for (var i = 0; i < nonDerived.size(); i++) { var prop = nonDerived.get(i); var getter = nonDerived.get(i).generateBuilderFieldName(); data.ensureImport(JodaBeanUtils.class); var base = "\t\t\tbuf.append(\"" + prop.getData().getPropertyName() + "\").append('=').append(JodaBeanUtils.toString(" + getter + "))"; addLine(0, base + join(i, nonDerived, ".append(',').append(' ');", ";")); } addLine(3, "buf.append('}');"); addLine(3, "return buf.toString();"); } addLine(2, "}"); addBlankLine(); return; } addLine(2, "@Override"); addLine(2, "public String toString() {"); addLine(3, "StringBuilder buf = new StringBuilder(" + (nonDerived.size() * 32 + 32) + ");"); addLine(3, "buf.append(\"" + data.getEffectiveBeanBuilderName() + "{\");"); addLine(3, "int len = buf.length();"); addLine(3, "toString(buf);"); addLine(3, "if (buf.length() > len) {"); addLine(4, "buf.setLength(buf.length() - 2);"); addLine(3, "}"); addLine(3, "buf.append('}');"); addLine(3, "return buf.toString();"); addLine(2, "}"); addBlankLine(); if (data.isSubClass()) { addLine(2, "@Override"); } addLine(2, "protected void toString(StringBuilder buf) {"); if (data.isSubClass()) { addLine(3, "super.toString(buf);"); } for (var prop : nonDerived) { var getter = prop.generateBuilderFieldName(); data.ensureImport(JodaBeanUtils.class); addLine(3, "buf.append(\"" + prop.getData().getPropertyName() + "\").append('=').append(JodaBeanUtils.toString(" + getter + ")).append(',').append(' ');"); } addLine(2, "}"); addBlankLine(); } //----------------------------------------------------------------------- private void addLines(List lines) { insertRegion.addAll(lines); } private void addLine(int tabCount, String line) { insertRegion.add("\t".repeat(tabCount) + line); } private void addBlankLine() { insertRegion.add(""); } private static String join(int i, List list, String join, String end) { return (i < list.size() - 1 ? join : end); } private static String joinComma(int i, List list, String end) { return join(i, list, ",", end); } boolean isBean() { return properties != null; } BeanData getData() { return data; } BeanGenConfig getConfig() { return config; } File getFile() { return file; } String getFieldPrefix() { return config.getPrefix(); } private List nonDerivedProperties() { List nonDerived = new ArrayList<>(); for (var prop : properties) { if (!prop.getData().isDerived()) { nonDerived.add(prop); } } return nonDerived; } private List nonDerivedEqualsHashCodeProperties() { List nonDerived = new ArrayList<>(); for (var prop : properties) { if (!prop.getData().isDerived() && !prop.getData().getEqualsHashCodeStyle().equals("omit")) { nonDerived.add(prop); } } return nonDerived; } private List toStringProperties() { List props = new ArrayList<>(); for (var prop : properties) { if (!"omit".equals(prop.getData().getToStringStyle())) { props.add(prop); } } return props; } } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanGenConfig.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; /** * Configuration for the code generator. */ public final class BeanGenConfig { /** * The copy generators. */ private final Map copyGenerators; /** * The builder types. */ private final Map builderTypes; /** * The builder generators. */ private final Map builderGenerators; /** * The invalid immutable types. */ private final Set invalidImmutableTypes; /** * The immutable varargs code. */ private final Map immutableVarArgs; /** * The immutable get clones. */ private final Map immutableGetClones; /** * The indent to use. */ private String indent = " "; /** * The field prefix to use. */ private String prefix = ""; /** * The end of line separator */ private String eol = System.lineSeparator(); /** * The default style to use. */ private String defaultStyle = "smart"; /** * Whether to add the generated annotation. */ private boolean generatedAnno; /** * Parses the configuration file. *

* This loads the file as an ini file in this package. * * @param resourceLocator the configuration resource locator, not null * @return the configuration */ public static BeanGenConfig parse(String resourceLocator) { var fileName = createConfigFileName(resourceLocator); try (var in = BeanGenConfig.class.getResourceAsStream(fileName)) { if (in == null) { throw new IllegalArgumentException("Configuration file not found in classpath: " + fileName); } try (var reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { var lines = reader.lines() .filter(line -> !line.trim().startsWith("#") && !line.trim().isEmpty()) .toList(); return parse(lines); } } catch (IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } } private static String createConfigFileName(String resourceLocator) { if (resourceLocator.contains("/") || resourceLocator.endsWith(".ini")) { return resourceLocator.startsWith("/") ? resourceLocator : "/" + resourceLocator; } else if (resourceLocator.equals("jdk6")) { // compatibility return "/org/joda/beans/gen/jdk.ini"; } else { return "/org/joda/beans/gen/" + resourceLocator + ".ini"; } } private static BeanGenConfig parse(List lines) { var immutableCopiers = new HashMap(); var mutableCopiers = new HashMap(); var immutableGetClones = new HashMap(); var immutableVarArgs = new HashMap(); var builderInits = new HashMap(); var builderTypes = new HashMap(); var invalidImmutableTypes = new HashSet(); for (var iterator = lines.listIterator(); iterator.hasNext();) { // CSIGNORE var line = iterator.next().trim(); switch (line) { case "[immutable.builder.to.immutable]" -> { parseConfig(iterator, immutableCopiers); } case "[immutable.builder.to.mutable]" -> { parseConfig(iterator, mutableCopiers); } case "[immutable.invalid.type]" -> { while (iterator.hasNext()) { line = iterator.next().trim(); var pos = line.indexOf('='); if (pos <= 0) { throw new IllegalArgumentException("Invalid ini file line: " + line); } var key = line.substring(0, pos).trim(); invalidImmutableTypes.add(key); } } case "[immutable.get.clone]" -> { while (iterator.hasNext()) { line = iterator.next().trim(); if (line.startsWith("[")) { iterator.previous(); break; } var pos = line.indexOf('='); if (pos <= 0) { throw new IllegalArgumentException("Invalid ini file line: " + line); } var key = line.substring(0, pos).trim(); var value = line.substring(pos + 1).trim(); if (!value.equals("clone") && !value.equals("cloneCast") && !value.equals("cloneArray")) { throw new IllegalArgumentException("Value for [immutable.get.clone] must be 'clone', 'cloneCast' or 'cloneArray'"); } immutableGetClones.put(key, value); } } case "[immutable.builder.varargs]" -> { parseConfig(iterator, immutableVarArgs); } case "[immutable.builder.type]" -> { parseConfig(iterator, builderTypes); } case "[immutable.builder.init]" -> { parseConfig(iterator, builderInits); } default -> throw new IllegalArgumentException("Invalid ini file section: " + line); } } // adjust to results var builderGenerators = new HashMap(); for (var entry : builderInits.entrySet()) { var type = builderTypes.get(entry.getKey()); if (type == null) { type = entry.getKey() + "<>"; } builderGenerators.put(entry.getKey(), new BuilderGen.PatternBuilderGen(type, entry.getValue())); } var copyGenerators = new HashMap(); for (var entry : immutableCopiers.entrySet()) { var fieldType = entry.getKey(); var immutableCopier = entry.getValue(); var mutableCopier = mutableCopiers.get(fieldType); if (mutableCopier == null) { throw new IllegalArgumentException("[immutable.builder.to.immutable] and [immutable.builder.to.mutable] entries must match: " + fieldType); } copyGenerators.put(fieldType, new CopyGen.PatternCopyGen(immutableCopier, mutableCopier, false)); } return new BeanGenConfig(copyGenerators, builderGenerators, builderTypes, invalidImmutableTypes, immutableVarArgs, immutableGetClones); } private static void parseConfig(ListIterator iterator, HashMap mutableMap) { while (iterator.hasNext()) { var line = iterator.next().trim(); if (line.startsWith("[")) { iterator.previous(); break; } var pos = line.indexOf('='); if (pos <= 0) { throw new IllegalArgumentException("Invalid ini file line: " + line); } var key = line.substring(0, pos).trim(); var value = line.substring(pos + 1).trim(); mutableMap.put(key, value); } } //----------------------------------------------------------------------- /** * Creates an instance. * * @param copyGenerators the copy generators, not null * @param builderGenerators the builder generators, not null * @param builderTypes the builder types, not null * @param invalidImmutableTypes the invalid immutable types, not null * @param immutableVarArgs the varargs code * @param immutableGetClones the get clone code */ private BeanGenConfig( Map copyGenerators, Map builderGenerators, Map builderTypes, Set invalidImmutableTypes, Map immutableVarArgs, Map immutableGetClones) { this.copyGenerators = copyGenerators; this.builderGenerators = builderGenerators; this.builderTypes = builderTypes; this.invalidImmutableTypes = invalidImmutableTypes; this.immutableVarArgs = immutableVarArgs; this.immutableGetClones = immutableGetClones; } //----------------------------------------------------------------------- /** * The copy generators. * * @return the generators, not null */ Map getCopyGenerators() { return copyGenerators; } /** * The builder generators. * * @return the generators, not null */ Map getBuilderGenerators() { return builderGenerators; } /** * The builder types. * * @return the types, not null */ public Map getBuilderTypes() { return builderTypes; } /** * The invalid immutable types. * * @return the invalid immutable types, not null */ public Set getInvalidImmutableTypes() { return invalidImmutableTypes; } /** * The builder varargs code. * * @return the varargs, not null */ public Map getImmutableVarArgs() { return immutableVarArgs; } /** * The builder types. * * @return the types, not null */ public Map getImmutableGetClones() { return immutableGetClones; } //----------------------------------------------------------------------- /** * Gets the indent to use. * * @return the indent, not null */ public String getIndent() { return indent; } /** * Sets the indent to use. * * @param indent the indent to use, not null */ public void setIndent(String indent) { this.indent = indent; } /** * Gets the prefix to use. * * @return the prefix, not null */ public String getPrefix() { return prefix; } /** * Sets the prefix to use. * * @param prefix the prefix to use, not null */ public void setPrefix(String prefix) { this.prefix = prefix; } /** * Gets the end of line separator to use. * * @return the end of line, not null */ public String getEol() { return eol; } /** * Sets the end of line separator to use. * * @param eol the end of line separator to use, not null */ public void setEol(String eol) { this.eol = eol; } /** * Gets the default style to use. * * @return the default style, not null */ public String getDefaultStyle() { return defaultStyle; } /** * Sets the default style to use. * * @param defaultStyle the default style to use, not null */ public void setDefaultStyle(String defaultStyle) { this.defaultStyle = defaultStyle; } /** * Gets whether to add the generated annotation. * * @return whether to add the generated annotation, not null */ public boolean isGeneratedAnno() { return generatedAnno; } /** * Sets whether to add the generated annotation. * * @param generatedAnno whether to add the generated annotation */ public void setGeneratedAnno(boolean generatedAnno) { this.generatedAnno = generatedAnno; } } ================================================ FILE: src/main/java/org/joda/beans/gen/BeanParser.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import static org.joda.beans.gen.BeanGen.CONSTRUCTOR_BY_ARGS; import static org.joda.beans.gen.BeanGen.CONSTRUCTOR_BY_BUILDER; import static org.joda.beans.gen.BeanGen.CONSTRUCTOR_NONE; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; /** * Parse bean information from source file. */ class BeanParser { /** Start marker. */ private static final String AUTOGENERATED_START_TEXT = "AUTOGENERATED START"; /** Start marker. */ private static final String AUTOGENERATED_START = "\t//------------------------- AUTOGENERATED START -------------------------"; /** End marker. */ private static final String AUTOGENERATED_END = "\t//-------------------------- AUTOGENERATED END --------------------------"; /** Pattern to find bean type. */ // handle three comma separated generic parameters // handle generic parameter extends clause // handle extends clause with further level of generic parameters // handle extends clause union types without generic parameters private static final Pattern BEAN_TYPE = Pattern.compile(".*class +(" + "([A-Z][A-Za-z0-9_]+)" + "(?:<" + "([A-Z])( +extends +[A-Za-z0-9_]+(?:[<][A-Za-z0-9_, ?]+[>])?(?:[ ]+[&][ ]+[A-Za-z0-9]+)*)?" + "(?:[,] +" + "([A-Z])( +extends +[A-Za-z0-9_]+(?:[<][A-Za-z0-9_, ?]+[>])?(?:[ ]+[&][ ]+[A-Za-z0-9]+)*)?" + "(?:[,] +" + "([A-Z])( +extends +[A-Za-z0-9_]+(?:[<][A-Za-z0-9_, ?]+[>])?(?:[ ]+[&][ ]+[A-Za-z0-9]+)*)?" + ")?" + ")?" + ">)?" + ").*"); /** Pattern to find super type. */ private static final Pattern SUPER_TYPE = Pattern.compile(".*extends +(" + "([A-Z][A-Za-z0-9_]+)" + "(?:<" + "([A-Z][A-Za-z0-9_<> ]*)" + "(?:[,] +" + "([A-Z][A-Za-z0-9_<> ]*)?" + "(?:[,] +" + "([A-Z][A-Za-z0-9_<> ]*)?" + ")?" + ")?" + ">)?" + ").*"); /** Pattern to find root type. */ private static final Pattern SUPER_IMPL_TYPE = Pattern.compile(".*implements.*[ ,]((Immutable)?Bean)([ ,{]|$).*"); /** Pattern to find serializable interface. */ private static final Pattern SERIALIZABLE_TYPE = Pattern.compile(".*implements.*[ ,]Serializable([ ,{]|$).*"); /** The style pattern. */ private static final Pattern STYLE_PATTERN = Pattern.compile(".*[ ,(]style[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The metaScope pattern. */ private static final Pattern META_SCOPE_PATTERN = Pattern.compile(".*[ ,(]metaScope[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The metaImplements pattern. */ private static final Pattern META_IMPLEMENTS_PATTERN = Pattern.compile(".*[ ,(]metaImplements[ ]*[=][ ]*[\"]([a-zA-Z0-9_.<>]*)[\"].*"); /** The builderScope pattern. */ private static final Pattern BUILDER_SCOPE_PATTERN = Pattern.compile(".*[ ,(]builderScope[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The builderStyle pattern. */ private static final Pattern BUILDER_NAME_PATTERN = Pattern.compile(".*[ ,(]builderName[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The constructorScope pattern. */ private static final Pattern CONSTRUCTOR_SCOPE_PATTERN = Pattern.compile(".*[ ,(]constructorScope[ ]*[=][ ]*[\"]([a-zA-Z@]*)[\"].*"); /** The factoryName pattern. */ private static final Pattern FACTORY_NAME_PATTERN = Pattern.compile(".*[ ,(]factoryName[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The hierarchy pattern. */ private static final Pattern HIERARCHY_PATTERN = Pattern.compile(".*[ ,(]hierarchy[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The cacheHashCode pattern. */ private static final Pattern CACHE_HASH_CODE_PATTERN = Pattern.compile(".*[ ,(]cacheHashCode[ ]*[=][ ]*(true|false).*"); /** The cloneStyle pattern. */ private static final Pattern CLONE_STYLE_PATTERN = Pattern.compile(".*[ ,(]cloneStyle[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The validator pattern. */ private static final Pattern VALIDATOR_PATTERN = Pattern.compile( ".*private[ ]+void[ ]+" + "([a-zA-Z][a-zA-Z0-9]*)[(][ ]*[)].*"); /** The defaults pattern. */ private static final Pattern DEFAULTS_PATTERN = Pattern.compile( ".*private[ ]+static[ ]+void[ ]+" + "([a-zA-Z][a-zA-Z0-9]*)[(][ ]*Builder[ ]+[a-zA-Z][a-zA-Z0-9]*[ ]*[)].*"); /** The content to process. */ private final File file; /** The content to process. */ private final List content; /** The content to process. */ private final BeanGenConfig config; /** The content to process. */ private int beanDefIndex; /** The start position of auto-generation. */ private int autoStartIndex; /** The end position of auto-generation. */ private int autoEndIndex; /** The list of property generators. */ private List properties; /** * Constructor. * @param file the file to process, not null * @param content the content to process, not null */ BeanParser(File file, List content, BeanGenConfig config) { this.file = file; this.content = content; this.config = config; } //----------------------------------------------------------------------- File getFile() { return file; } String getFieldPrefix() { return config.getPrefix(); } BeanGenConfig getConfig() { return config; } //----------------------------------------------------------------------- BeanGen parse() { var data = new BeanData(); beanDefIndex = parseBeanDefinition(); data.getCurrentImports().addAll(parseImports(beanDefIndex)); data.setImportInsertLocation(parseImportLocation(beanDefIndex)); if (beanDefIndex < 0) { return new BeanGen(file, content, config, data); } data.setBeanStyle(parseBeanStyle(beanDefIndex)); data.resolveBeanStyle(config.getDefaultStyle()); if (!data.isBeanStyleValid()) { throw new BeanCodeGenException("Invalid bean style: " + data.getBeanStyle(), file, beanDefIndex); } data.setConstructorScope(parseConstructorScope(beanDefIndex)); if (!data.isConstructorScopeValid()) { throw new BeanCodeGenException("Invalid constructor scope: " + data.getConstructorScope(), file, beanDefIndex); } data.setBeanMetaScope(parseBeanMetaScope(beanDefIndex)); if (!data.isBeanMetaScopeValid()) { throw new BeanCodeGenException("Invalid meta-bean scope: " + data.getBeanMetaScope(), file, beanDefIndex); } data.setBeanMetaImplements(parseBeanMetaImplements(beanDefIndex)); data.setBeanBuilderScope(parseBeanBuilderScope(beanDefIndex)); if (!data.isBeanBuilderScopeValid()) { throw new BeanCodeGenException("Invalid bean builder scope: " + data.getBeanBuilderScope(), file, beanDefIndex); } data.setBeanBuilderName(parseBeanBuilderName(beanDefIndex)); data.setFactoryName(parseFactoryName(beanDefIndex)); data.setCacheHashCode(parseCacheHashCode(beanDefIndex)); data.setCloneStyle(parseCloneStyle(beanDefIndex)); if (!data.isCloneStyleValid()) { throw new BeanCodeGenException("Invalid clone style: " + data.getCloneStyle(), file, beanDefIndex); } data.setImmutableConstructor(parseImmutableConstructor(beanDefIndex)); data.setConstructable(parseConstructable(beanDefIndex)); data.setTypeParts(parseBeanType(beanDefIndex)); var classHeaderAfterType = classHeaderAfterType(beanDefIndex, data.getType()); data.setSuperTypeParts(parseBeanSuperType(classHeaderAfterType)); data.setSerializable(parseSerializable(classHeaderAfterType)); if (parseBeanHierarchy(beanDefIndex).equals("immutable")) { data.setImmutable(true); data.setConstructorStyle(CONSTRUCTOR_BY_BUILDER); } else if (data.getImmutableConstructor() == CONSTRUCTOR_NONE) { if (data.isImmutable()) { if (data.isTypeFinal()) { data.setConstructorStyle(CONSTRUCTOR_BY_ARGS); } else { data.setConstructorStyle(CONSTRUCTOR_BY_BUILDER); } } else { if (data.isBeanStyleLight()) { data.setConstructorStyle(CONSTRUCTOR_BY_ARGS); } else { data.setConstructorStyle(CONSTRUCTOR_BY_BUILDER); } } } else { data.setConstructorStyle(data.getImmutableConstructor()); } if (data.isImmutable()) { data.setImmutableValidator(parseImmutableValidator(beanDefIndex)); data.setImmutableDefaults(parseImmutableDefaults(beanDefIndex)); data.setImmutablePreBuild(parseImmutablePreBuild(beanDefIndex)); if (data.isBeanStyleLight() && !data.isTypeFinal()) { throw new BeanCodeGenException( "Invalid bean style: Light beans must be declared final", file, beanDefIndex); } if (data.isBeanStyleMinimal() && !data.isTypeFinal()) { throw new BeanCodeGenException( "Invalid bean style: Minimal beans must be declared final", file, beanDefIndex); } if (data.isFactoryRequired() && !data.isRootClass()) { throw new BeanCodeGenException( "Invalid bean style: Factory method only allowed when bean has no bean superclass", file, beanDefIndex); } if (data.isFactoryRequired() && !data.isTypeFinal()) { throw new BeanCodeGenException( "Invalid bean style: Factory method only allowed when bean is final", file, beanDefIndex); } } else { if (data.isBeanStyleLight() && !data.isTypeFinal()) { throw new BeanCodeGenException( "Invalid bean style: Light beans must be declared final", file, beanDefIndex); } if (data.isBeanStyleMinimal() && !data.isTypeFinal()) { throw new BeanCodeGenException( "Invalid bean style: Minimal beans must be declared final", file, beanDefIndex); } if (data.isFactoryRequired()) { throw new BeanCodeGenException( "Invalid bean style: Factory method only allowed when bean is immutable", file, beanDefIndex); } } properties = parseProperties(data); autoStartIndex = parseStartAutogen(); autoEndIndex = parseEndAutogen(); data.setManualSerializationId(parseManualSerializationId(beanDefIndex)); data.setManualClone(parseManualClone(beanDefIndex)); data.setManualEqualsHashCode(parseManualEqualsHashCode(beanDefIndex)); data.setManualToStringCode(parseManualToStringCode(beanDefIndex)); if (data.isImmutable()) { for (var prop : properties) { if (!prop.getData().isDerived() && !prop.getData().isFinal()) { throw new BeanCodeGenException("ImmutableBean must have final properties: " + data.getTypeRaw() + "." + prop.getData().getFieldName(), file, prop.getData().getLineIndex()); } } } else { if (data.getImmutableConstructor() > CONSTRUCTOR_NONE) { throw new BeanCodeGenException("Mutable beans must not specify @ImmutableConstructor: " + data.getTypeRaw(), file, beanDefIndex); } if (!"smart".equals(data.getConstructorScope()) && !data.isBeanStyleLight()) { throw new BeanCodeGenException("Mutable beans must not specify @BeanDefinition(constructorScope): " + data.getTypeRaw(), file, beanDefIndex); } } if (data.isCacheHashCode()) { data.setCacheHashCode(data.isImmutable() && !data.isManualEqualsHashCode()); } return new BeanGen(file, content, config, data, properties, autoStartIndex, autoEndIndex); } private String classHeaderAfterType(int defLine, String fullType) { var buf = new StringBuilder(128); var matchedType = false; for (var index = defLine; index < content.size(); index++) { var line = content.get(index); if (!matchedType) { if (!line.contains(fullType)) { continue; } matchedType = true; line = line.substring(line.indexOf(fullType) + fullType.length()); } buf.append(line).append(' '); if (line.trim().endsWith("{") && !line.trim().startsWith("@")) { break; } } return buf.toString().trim(); } //----------------------------------------------------------------------- private int parseBeanDefinition() { for (var index = 0; index < content.size(); index++) { var line = content.get(index).trim(); if (line.startsWith("@BeanDefinition")) { return index; } } return -1; } private Set parseImports(int defLine) { var end = defLine < 0 ? content.size() : defLine; Set imports = new HashSet<>(); for (var index = 0; index < end; index++) { if (content.get(index).startsWith("import ")) { var imp = content.get(index).substring(7).trim(); imp = imp.substring(0, imp.indexOf(';')); if (!imp.endsWith(".*")) { imports.add(imp); } } } return imports; } private int parseImportLocation(int defLine) { var end = defLine < 0 ? content.size() : defLine; var location = 0; for (var index = 0; index < end; index++) { if (content.get(index).startsWith("import ") || content.get(index).startsWith("package ")) { location = index; } } return location; } private String parseBeanStyle(int defLine) { var line = content.get(defLine).trim(); var matcher = STYLE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseConstructorScope(int defLine) { var line = content.get(defLine).trim(); var matcher = CONSTRUCTOR_SCOPE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseBeanMetaScope(int defLine) { var line = content.get(defLine).trim(); var matcher = META_SCOPE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseBeanMetaImplements(int defLine) { var line = content.get(defLine).trim(); var matcher = META_IMPLEMENTS_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return ""; } private String parseBeanBuilderScope(int defLine) { var line = content.get(defLine).trim(); var matcher = BUILDER_SCOPE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseBeanBuilderName(int defLine) { var line = content.get(defLine).trim(); var matcher = BUILDER_NAME_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return ""; } private String parseFactoryName(int defLine) { var line = content.get(defLine).trim(); var matcher = FACTORY_NAME_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return ""; } private String parseBeanHierarchy(int defLine) { var line = content.get(defLine).trim(); var matcher = HIERARCHY_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return ""; } private boolean parseCacheHashCode(int defLine) { var line = content.get(defLine).trim(); var matcher = CACHE_HASH_CODE_PATTERN.matcher(line); if (matcher.matches()) { return Boolean.parseBoolean(matcher.group(1)); } return false; } private String parseCloneStyle(int defLine) { var line = content.get(defLine).trim(); var matcher = CLONE_STYLE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private boolean parseConstructable(int defLine) { for (var index = defLine; index < content.size(); index++) { if (content.get(index).contains(" abstract class ")) { return false; } } return true; } private String[] parseBeanType(int defLine) { var matcher = BEAN_TYPE.matcher(""); for (var index = defLine; index < content.size(); index++) { var line = content.get(index); matcher.reset(line); if (matcher.matches()) { var startStr = line.substring(0, matcher.start(1)); var fnl = startStr.contains(" final ") || startStr.startsWith("final ") ? "final" : null; var scope = startStr.contains("public ") ? "public" : "package"; scope = startStr.contains("protected ") ? "protected" : scope; scope = startStr.contains("private ") ? "private" : scope; return new String[] {fnl, scope, matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5), matcher.group(6), matcher.group(7), matcher.group(8)}; } if (line.contains(AUTOGENERATED_START_TEXT)) { break; } } throw new BeanCodeGenException("Unable to locate bean class name", file, beanDefIndex); } private String[] parseBeanSuperType(String classHeaderAfterType) { // this uses classHeaderAfterType as extends has two meanings in class headers // search for implements var matcherImplements = SUPER_IMPL_TYPE.matcher(classHeaderAfterType); if (matcherImplements.matches()) { return new String[] {matcherImplements.group(1)}; } // search for extends var matcherExtends = SUPER_TYPE.matcher(classHeaderAfterType); if (matcherExtends.matches()) { return new String[] {matcherExtends.group(1), matcherExtends.group(2), matcherExtends.group(3), matcherExtends.group(4), matcherExtends.group(5)}; } throw new BeanCodeGenException("Unable to locate bean superclass", file, beanDefIndex); } private boolean parseSerializable(String classHeaderAfterType) { return SERIALIZABLE_TYPE.matcher(classHeaderAfterType).matches(); } private boolean parseManualSerializationId(int defLine) { for (var index = defLine; index < autoStartIndex; index++) { if (content.get(index).trim().startsWith("private static final long serialVersionUID")) { return true; } } return false; } private int parseImmutableConstructor(int defLine) { var found = CONSTRUCTOR_NONE; for (var index = defLine; index < content.size(); index++) { if (content.get(index).trim().equals("@ImmutableConstructor")) { if (found > 0) { throw new BeanCodeGenException("Only one @ImmutableConstructor may be specified", file, index); } found = CONSTRUCTOR_BY_ARGS; if (index + 1 < content.size()) { var nextLine = content.get(index + 1); if (nextLine.contains("Builder ") || nextLine.contains("Builder<")) { found = CONSTRUCTOR_BY_BUILDER; } } } } return found; } private String parseImmutableValidator(int defLine) { var found = false; for (var index = defLine; index < content.size(); index++) { if (content.get(index).trim().equals("@ImmutableValidator")) { if (found) { throw new BeanCodeGenException("Only one @ImmutableValidator may be specified", file, index); } found = true; if (index + 1 < content.size()) { var nextLine = content.get(index + 1); var matcher = VALIDATOR_PATTERN.matcher(nextLine); if (matcher.matches()) { return matcher.group(1); } throw new BeanCodeGenException( "@ImmutableValidator method must be private void and no-args", file, index + 1); } } } return null; } private String parseImmutableDefaults(int defLine) { var found = false; for (var index = defLine; index < content.size(); index++) { if (content.get(index).trim().equals("@ImmutableDefaults")) { if (found) { throw new BeanCodeGenException("Only one @ImmutableDefaults may be specified", file, index); } found = true; if (index + 1 < content.size()) { var nextLine = content.get(index + 1); var matcher = DEFAULTS_PATTERN.matcher(nextLine); if (matcher.matches()) { return matcher.group(1); } throw new BeanCodeGenException( "@ImmutableDefaults method must be private static void and have one argument of type 'Builder'", file, index + 1); } } } return null; } private String parseImmutablePreBuild(int defLine) { var found = false; for (var index = defLine; index < content.size(); index++) { if (content.get(index).trim().equals("@ImmutablePreBuild")) { if (found) { throw new BeanCodeGenException("Only one @ImmutablePreBuild may be specified", file, index); } found = true; if (index + 1 < content.size()) { var nextLine = content.get(index + 1); var matcher = DEFAULTS_PATTERN.matcher(nextLine); if (matcher.matches()) { return matcher.group(1); } throw new BeanCodeGenException( "@ImmutablePreBuild method must be private static void and have one argument of type 'Builder'", file, index + 1); } } } return null; } private List parseProperties(BeanData data) { List props = new ArrayList<>(); for (var index = 0; index < content.size(); index++) { var line = content.get(index).trim(); var parser = new PropertyParser(this); if (line.startsWith("@PropertyDefinition")) { var prop = parser.parse(data, content, index); props.add(prop); data.getProperties().add(prop.getData()); } else if (line.startsWith("@DerivedProperty")) { var prop = parser.parseDerived(data, content, index); props.add(prop); data.getProperties().add(prop.getData()); } } return props; } private int parseStartAutogen() { for (var index = 0; index < content.size(); index++) { var line = content.get(index).trim(); if (line.contains(" AUTOGENERATED START ")) { content.set(index, AUTOGENERATED_START); return index; } } for (var index = content.size() - 1; index >= 0; index--) { var line = content.get(index).trim(); if (line.equals("}")) { content.add(index, AUTOGENERATED_START); return index; } if (!line.isEmpty()) { break; } } throw new BeanCodeGenException("Unable to locate start autogeneration point", file, beanDefIndex); } private int parseEndAutogen() { for (var index = autoStartIndex; index < content.size(); index++) { var line = content.get(index).trim(); if (line.contains(" AUTOGENERATED END ")) { content.set(index, AUTOGENERATED_END); return index; } } content.add(autoStartIndex + 1, AUTOGENERATED_END); return autoStartIndex + 1; } private boolean parseManualClone(int defLine) { for (var index = defLine; index < autoStartIndex; index++) { var line = content.get(index).trim(); if (line.startsWith("public ") && line.endsWith(" clone() {")) { return true; } } return false; } private boolean parseManualEqualsHashCode(int defLine) { for (var index = defLine; index < autoStartIndex; index++) { var line = content.get(index).trim(); if (line.equals("public int hashCode() {") || (line.startsWith("public boolean equals(") && line.endsWith(") {"))) { return true; } } return false; } private boolean parseManualToStringCode(int defLine) { for (var index = defLine; index < autoStartIndex; index++) { var line = content.get(index).trim(); if (line.equals("public String toString() {")) { return true; } } return false; } } ================================================ FILE: src/main/java/org/joda/beans/gen/BuilderGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.List; /** * A generator of builder code. */ abstract class BuilderGen { /** * Generates the builder field. * * @param indent the indent to use, not null * @param prop the property data, not null * @return the generated code, not null */ abstract List generateField(String indent, PropertyData prop); /** * Is special initialization needed. * * @param prop the property data, not null * @return true if special */ abstract boolean isSpecialInit(PropertyData prop); /** * Generates the init string. * * @param prop the property data, not null * @return the generated code, not null */ abstract String generateInit(PropertyData prop); /** * Generates the builder exposed type. * * @param prop the property data, not null * @return the generated code, not null */ String generateType(PropertyData prop) { return prop.getBuilderType(); } //----------------------------------------------------------------------- static class PatternBuilderGen extends BuilderGen { private final String type; private final String init; PatternBuilderGen(String type, String init) { this.type = type; this.init = init; } @Override List generateField(String indent, PropertyData prop) { if (prop.isNotNull()) { var init = this.init.replace("<>", PropertyGen.resolveWildcard(prop.getTypeGenerics())); return List.of(indent + "private " + generateType(prop) + " " + prop.getFieldName() + " = " + init + ";"); } else { return List.of(indent + "private " + generateType(prop) + " " + prop.getFieldName() + ";"); } } @Override boolean isSpecialInit(PropertyData prop) { return true; } @Override String generateInit(PropertyData prop) { return init; } @Override String generateType(PropertyData prop) { if (!"smart".equals(prop.getBuilderTypeStyle())) { return prop.getBuilderType().replace("<>", prop.getTypeGenerics()); } return type.replace("<>", prop.getTypeGenerics()); } } static class SimpleBuilderGen extends BuilderGen { SimpleBuilderGen() { } @Override List generateField(String indent, PropertyData prop) { return List.of(indent + "private " + generateType(prop) + " " + prop.getFieldName() + ";"); } @Override boolean isSpecialInit(PropertyData prop) { return false; } @Override String generateInit(PropertyData prop) { return defaultType(prop); } @Override String generateType(PropertyData prop) { return prop.getBuilderType().replace("<>", prop.getTypeGenerics()); } } static class NoBuilderGen extends BuilderGen { static final BuilderGen INSTANCE = new NoBuilderGen(); @Override List generateField(String indent, PropertyData prop) { return List.of(); } @Override boolean isSpecialInit(PropertyData prop) { return false; } @Override String generateInit(PropertyData prop) { return defaultType(prop); } } // default type (assigned to an Object) private static String defaultType(PropertyData prop) { return switch (prop.getType()) { case "long" -> "0L"; case "int" -> "0"; case "short" -> "(short) 0"; case "byte" -> "(byte) 0"; case "double" -> "0d"; case "float" -> "0f"; case "char" -> "'\\u0000'"; case "boolean" -> "Boolean.FALSE"; default -> "null"; }; } } ================================================ FILE: src/main/java/org/joda/beans/gen/CopyGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.ArrayList; import java.util.List; /** * A generator of copy code. */ abstract class CopyGen { /** * Generates the copy to immutable lines. * * @param indent the indent to use, not null * @param fromBean the source code for the bean to copy from, not null * @param prop the property data, not null * @return the generated code, not null */ abstract List generateCopyToImmutable(String indent, String fromBean, PropertyData prop); /** * Generates the copy to mutable lines. * * @param indent the indent to use, not null * @param prop the property data, not null * @param beanToCopyFrom the variable name of the bean, not null * @return the generated code, not null */ abstract List generateCopyToMutable(String indent, PropertyData prop, String beanToCopyFrom); //----------------------------------------------------------------------- static class PatternCopyGen extends CopyGen { static final CopyGen ASSIGN = new PatternCopyGen("$field = $value;", true); static final CopyGen CLONE = new PatternCopyGen("$value.clone()", false); static final CopyGen CLONE_CAST = new PatternCopyGen("($type) $value.clone()", false); static final CopyGen CLONE_ARRAY = new PatternCopyGen("($type) JodaBeanUtils.cloneArray($value)", true); private final String immutablePattern; private final String mutablePattern; private final boolean nullSafe; PatternCopyGen(String pattern, boolean nullSafe) { this(pattern, pattern, nullSafe); } PatternCopyGen(String immutablePattern, String mutablePattern, boolean nullSafe) { this.immutablePattern = immutablePattern; this.mutablePattern = mutablePattern; this.nullSafe = nullSafe; } @Override List generateCopyToImmutable(String indent, String fromBean, PropertyData prop) { var list = new ArrayList(); var split = immutablePattern.split("\n"); for (var line : split) { if (split.length == 1) { if (!line.startsWith("$field = ") && !line.endsWith(";")) { if (nullSafe || prop.isNotNull()) { line = "$field = " + line + ";"; } else { line = "$field = ($value != null ? " + line + " : null);"; } } if (!line.startsWith("$field = ")) { line = "$field = " + line; } } line = line.replace("$field", "this." + prop.getFieldName()); line = line.replace("$value", fromBean + (fromBean.isEmpty() ? prop.getPropertyName() : prop.getFieldName())); line = line.replace("$type", prop.getFieldType()); line = line.replace("$typeRaw", prop.getTypeRaw()); line = line.replace("$generics", prop.getTypeGenerics()); list.add(indent + line); } return list; } @Override List generateCopyToMutable(String indent, PropertyData prop, String beanToCopyFrom) { var list = new ArrayList(); var split = mutablePattern.split("\n"); for (var line : split) { if (split.length == 1) { if (!line.startsWith("$field = ") && !line.endsWith(";")) { if (nullSafe || prop.isNotNull()) { line = "$field = " + line + ";"; } else { if (line.equals("$value")) { line = "$field = $value;"; } else { line = "$field = ($value != null ? " + line + " : null);"; } } } if (!line.startsWith("$field = ")) { line = "$field = " + line; } } line = line.replace("$field", "this." + prop.getFieldName()); line = line.replace("$value", beanToCopyFrom + "." + prop.getGetterGen().generateGetInvoke(prop)); line = line.replace("$type", prop.getFieldType()); line = line.replace("$typeRaw", prop.getTypeRaw()); line = line.replace("$generics", prop.getTypeGenerics()); list.add(indent + line); } return list; } } static class NoCopyGen extends CopyGen { static final CopyGen INSTANCE = new NoCopyGen(); @Override List generateCopyToImmutable(String indent, String fromBean, PropertyData prop) { return List.of(); } @Override List generateCopyToMutable(String indent, PropertyData prop, String beanToCopyFrom) { return List.of(); } } } ================================================ FILE: src/main/java/org/joda/beans/gen/DerivedProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining a derived property accessor for code generation. *

* This annotation is used on a getter to indicate that the method is used to * provide a derived property. A derived property has no instance variable. * A derived property will not form part of the {@code equals()} or {@code hashCode()} * methods, but will be included in {@code toString()}. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DerivedProperty { } ================================================ FILE: src/main/java/org/joda/beans/gen/GetterGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.ArrayList; import java.util.List; /** * A generator of get methods. */ abstract class GetterGen { /** * Generates the getter method. * @param prop the property data, not null * @return the generated code, not null */ abstract List generateGetter(PropertyData prop); /** * Generates the getter method invocation. * This is just the method name. * @param prop the property data, not null * @return the generated code, not null */ String generateGetInvoke(PropertyData prop) { return "get" + prop.getUpperName() + "()"; } //----------------------------------------------------------------------- static final class GetGetterGen extends GetterGen { static final GetGetterGen PUBLIC = new GetGetterGen("public "); static final GetGetterGen PROTECTED = new GetGetterGen("protected "); static final GetGetterGen PACKAGE = new GetGetterGen(""); static final GetGetterGen PRIVATE = new GetGetterGen("private "); private final String access; static GetGetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private GetGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "get", prop.getFieldName()); } } static final class IsGetterGen extends GetterGen { static final IsGetterGen PUBLIC = new IsGetterGen("public "); static final IsGetterGen PROTECTED = new IsGetterGen("protected "); static final IsGetterGen PACKAGE = new IsGetterGen(""); static final IsGetterGen PRIVATE = new IsGetterGen("private "); private final String access; static IsGetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private IsGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "is", prop.getFieldName()); } @Override String generateGetInvoke(PropertyData prop) { return "is" + prop.getUpperName() + "()"; } } static final class CloneNNGetterGen extends GetterGen { static final GetterGen PUBLIC = new CloneNNGetterGen("public "); static final GetterGen PROTECTED = new CloneNNGetterGen("protected "); static final GetterGen PACKAGE = new CloneNNGetterGen(""); static final GetterGen PRIVATE = new CloneNNGetterGen("private "); private final String access; static GetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private CloneNNGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "get", prop.getFieldName() + ".clone()"); } } static final class CloneGetterGen extends GetterGen { static final GetterGen PUBLIC = new CloneGetterGen("public "); static final GetterGen PROTECTED = new CloneGetterGen("protected "); static final GetterGen PACKAGE = new CloneGetterGen(""); static final GetterGen PRIVATE = new CloneGetterGen("private "); private final String access; static GetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private CloneGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "get", "(" + prop.getFieldName() + " != null ? " + prop.getFieldName() + ".clone() : null)"); } } static final class CloneCastNNGetterGen extends GetterGen { static final GetterGen PUBLIC = new CloneCastNNGetterGen("public "); static final GetterGen PROTECTED = new CloneCastNNGetterGen("protected "); static final GetterGen PACKAGE = new CloneCastNNGetterGen(""); static final GetterGen PRIVATE = new CloneCastNNGetterGen("private "); private final String access; static GetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private CloneCastNNGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "get", "(" + prop.getFieldType() + ") " + prop.getFieldName() + ".clone()"); } } static final class CloneCastGetterGen extends GetterGen { static final GetterGen PUBLIC = new CloneCastGetterGen("public "); static final GetterGen PROTECTED = new CloneCastGetterGen("protected "); static final GetterGen PACKAGE = new CloneCastGetterGen(""); static final GetterGen PRIVATE = new CloneCastGetterGen("private "); private final String access; static GetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private CloneCastGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "get", "(" + prop.getFieldName() + " != null ? (" + prop.getFieldType() + ") " + prop.getFieldName() + ".clone() : null)"); } } static final class CloneArrayGetterGen extends GetterGen { static final GetterGen PUBLIC = new CloneArrayGetterGen("public "); static final GetterGen PROTECTED = new CloneArrayGetterGen("protected "); static final GetterGen PACKAGE = new CloneArrayGetterGen(""); static final GetterGen PRIVATE = new CloneArrayGetterGen("private "); private final String access; static GetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private CloneArrayGetterGen(String access) { this.access = access; } @Override List generateGetter(PropertyData prop) { return doGenerateGetter(prop, access, "get", "(" + prop.getFieldType() + ") JodaBeanUtils.cloneArray(" + prop.getFieldName() + ")"); } } static final class Optional8GetterGen extends GetterGen { static final GetterGen PUBLIC = new Optional8GetterGen(); @Override List generateGetter(PropertyData prop) { var list = new ArrayList(); list.add("\t/**"); list.add("\t * Gets " + prop.getFirstComment()); for (var comment : prop.getComments()) { list.add("\t * " + comment); } list.add("\t * @return the optional value of the property, not null"); if (prop.getDeprecatedComment() != null) { list.add("\t * " + prop.getDeprecatedComment()); } list.add("\t */"); if (prop.isOverrideGet()) { list.add("\t@Override"); } if (prop.isDeprecated()) { list.add("\t@Deprecated"); } switch (prop.getType()) { case "Double" -> { list.add("\tpublic OptionalDouble get" + prop.getUpperName() + "() {"); list.add("\t\treturn " + prop.getFieldName() + " != null ? " + "OptionalDouble.of(" + prop.getFieldName() + ") : OptionalDouble.empty();"); } case "Integer" -> { list.add("\tpublic OptionalInt get" + prop.getUpperName() + "() {"); list.add("\t\treturn " + prop.getFieldName() + " != null ? " + "OptionalInt.of(" + prop.getFieldName() + ") : OptionalInt.empty();"); } case "Long" -> { list.add("\tpublic OptionalLong get" + prop.getUpperName() + "() {"); list.add("\t\treturn " + prop.getFieldName() + " != null ? " + "OptionalLong.of(" + prop.getFieldName() + ") : OptionalLong.empty();"); } case null, default -> { list.add("\tpublic Optional<" + prop.getType() + "> get" + prop.getUpperName() + "() {"); list.add("\t\treturn Optional.ofNullable(" + prop.getFieldName() + ");"); } } list.add("\t}"); list.add(""); return list; } @Override String generateGetInvoke(PropertyData prop) { return prop.getFieldName(); } } static final class OptionalGuavaGetterGen extends GetterGen { static final GetterGen PUBLIC = new OptionalGuavaGetterGen(); @Override List generateGetter(PropertyData prop) { var list = new ArrayList(); list.add("\t/**"); list.add("\t * Gets " + prop.getFirstComment()); for (var comment : prop.getComments()) { list.add("\t * " + comment); } list.add("\t * @return the optional value of the property, not null"); if (prop.getDeprecatedComment() != null) { list.add("\t * " + prop.getDeprecatedComment()); } list.add("\t */"); if (prop.isOverrideGet()) { list.add("\t@Override"); } if (prop.isDeprecated()) { list.add("\t@Deprecated"); } list.add("\tpublic Optional<" + prop.getType() + "> get" + prop.getUpperName() + "() {"); list.add("\t\treturn Optional.fromNullable(" + prop.getFieldName() + ");"); list.add("\t}"); list.add(""); return list; } @Override String generateGetInvoke(PropertyData prop) { return prop.getFieldName(); } } static class ManualGetterGen extends GetterGen { static final GetterGen INSTANCE = new ManualGetterGen(); @Override List generateGetter(PropertyData prop) { return List.of(); } } static class NoGetterGen extends GetterGen { static final GetterGen INSTANCE = new NoGetterGen(); @Override List generateGetter(PropertyData prop) { return List.of(); } @Override String generateGetInvoke(PropertyData prop) { return prop.getFieldName(); } } private static List doGenerateGetter(PropertyData prop, String access, String prefix, String expression) { var list = new ArrayList(); list.add("\t/**"); list.add("\t * Gets " + prop.getFirstComment()); for (var comment : prop.getComments()) { list.add("\t * " + comment); } list.add("\t * @return the value of the property" + prop.getNotNullJavadoc()); if (prop.getDeprecatedComment() != null) { list.add("\t * " + prop.getDeprecatedComment()); } list.add("\t */"); if (prop.isOverrideGet()) { list.add("\t@Override"); } if (prop.isDeprecated()) { list.add("\t@Deprecated"); } list.add("\t" + access + prop.getType() + " " + prefix + prop.getUpperName() + "() {"); list.add("\t\treturn " + expression + ";"); list.add("\t}"); list.add(""); return list; } } ================================================ FILE: src/main/java/org/joda/beans/gen/ImmutableConstructor.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining which constructor is to be used to create the object * in for code generation of immutable beans. *

* The constructor must have the same arguments and types as the properties * as exposed by the builder. They must also be in the same order. * The constructor is responsible for maintaining the invariants of the class, * such as validation. *

* For example, a property type of 'ImmutableList<Foo>' will have a builder * type of 'List<Foo>', thus the constructor must also use 'List'. *

* If no constructor specifies this annotation then a constructor will be generated. * In many cases it is easiest to generate the constructor, then move it outside * the autogenerated block and annotate it. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.CONSTRUCTOR) public @interface ImmutableConstructor { } ================================================ FILE: src/main/java/org/joda/beans/gen/ImmutableDefaults.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining which method is to be used to apply the default property values * when code generating immutable beans. *

* Each non-collection property in an immutable bean normally has to be initialized before use. * This annotation allows default values to be set when creating the builder. * Note that the defaults apply to the builder, not to the constructor of the bean. *

* The method must be a private static void instance method that takes a single argument of the type 'Builder'. * Private is necessary as it is called from the builder constructor. * For example: *

 *   {@literal @}ImmutableDefaults
 *   private static void applyDefaults(Builder builder) {
 *     builder.group(Group.STANDARD);  // default the group property to 'STANDARD'
 *   }
 * 
*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ImmutableDefaults { } ================================================ FILE: src/main/java/org/joda/beans/gen/ImmutablePreBuild.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining a method that is to be called just before a code generated immutable bean is built. *

* This is used when an immutable bean wants to perform an action on the builder just * before it is built into a bean. The action might include validation (normally done * using {@link ImmutableValidator}) and defaulting (normally done using {@link ImmutableDefaults}). *

* The special use case for this annotation is the ability to default the value of one property * from the value of another. For example, consider a bean with two dates, where one is derived * from the other (such as the second being the first adjusted to a valid business day). * Use of this annotation allows the second date to be set to the same as the first date if * a value is not set. *

* The method must be a private static void instance method that takes a single argument of the type 'Builder'. * The method will be called at the start of the {@code build()} method of the builder. * For example: *

 *   {@literal @}ImmutablePreBuild
 *   private static void preBuild(Builder builder) {
 *     if (builder.date2 == null) {
 *       builder.date2 = builder.date1;  // default date2 to be same as date1
 *     }
 *   }
 * 
*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ImmutablePreBuild { } ================================================ FILE: src/main/java/org/joda/beans/gen/ImmutableValidator.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining which method is to be used to validate the bean * when code generating immutable beans. *

* Each property in a bean can be independently validated. * This annotation allows properties to be cross-checked at the end of the constructor. *

* The method must be a private void instance method and take no arguments. * Private is necessary as it is called from the constructor. * For example: *

 *   {@literal @}ImmutableValidator
 *   private void validate() {
 *     if (age != null && age {@literal <} 0) {
 *       throw new IllegalArgumentException("Age must not be negative if specified")
 *     }
 *   }
 * 
*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ImmutableValidator { } ================================================ FILE: src/main/java/org/joda/beans/gen/PropertyData.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.StringTokenizer; import org.joda.beans.PropertyStyle; import org.joda.beans.gen.CopyGen.PatternCopyGen; /** * A bean that can be generated. */ class PropertyData { /** Collection types. */ private static final Set COLLECTIONS = Set.of( "Collection", "Set", "SortedSet", "NavigableSet", "List", "ArrayList", "LinkedList", "HashSet", "LinkedHashSet", "TreeSet", "ConcurrentSkipListSet, EnumSet", "ImmutableCollection", "ImmutableList", "ImmutableSet", "ImmutableSortedSet"); /** Set types. */ private static final Set SETS = Set.of( "Set", "SortedSet", "NavigableSet", "HashSet", "LinkedHashSet", "TreeSet", "ConcurrentSkipListSet, EnumSet", "ImmutableSet", "ImmutableSortedSet"); /** Set types. */ private static final Set SORTED_SETS = Set.of( "SortedSet", "NavigableSet", "TreeSet", "ConcurrentSkipListSet", "ImmutableSortedSet"); /** Map types. */ private static final Set MAPS = Set.of( "Map", "SortedMap", "NavigableMap", "ConcurrentMap", "ConcurrentNavigableMap", "HashMap", "LinkedHashMap", "TreeMap", "ConcurrentHashMap", "ConcurrentSkipListMap", "BiMap", "HashBiMap", "ImmutableMap", "ImmutableSortedMap", "ImmutableBiMap"); /** Owning bean. */ private final BeanData bean; /** Annotation line index for {@code PropertyDefinition} in input file. */ private final int lineIndex; /** Property name. */ private String propertyName; /** Field name. */ private String fieldName; /** Meta field name. */ private String metaFieldName; /** Upper property name. */ private String upperName; /** Property type. */ private String type; /** The builder type. */ private String builderType; /** Property field type. */ private String fieldType; /** Whether the field is declared final. */ private boolean isFinal; /** The field initializer. */ private String initializer; /** The alias. */ private String alias; /** The getter style. */ private String getStyle; /** The setter style. */ private String setStyle; /** The override style. */ private boolean overrideGet; /** The override style. */ private boolean overrideSet; /** The type style. */ private String typeStyle; /** The builder type style. */ private String builderTypeStyle; /** The equals hashCode style. */ private String equalsHashCodeStyle; /** The toString style. */ private String toStringStyle; /** The validation string. */ private String validation; /** Deprecated flag. */ private boolean deprecated; /** First comment about the property. */ private String firstComment; /** Other comments about the property. */ private final List comments = new ArrayList<>(); /** Deprecated comment about the property, null if not deprecated. */ private String deprecatedComment; /** The getter generator. */ private GetterGen getterGen; /** The setter generator. */ private SetterGen setterGen; /** The flag for bound properties. */ private boolean bound; /** The copy generator. */ private CopyGen copyGen; /** The builder generator. */ private BuilderGen builderGen; /** The config. */ private BeanGenConfig config; /** * Constructor. */ PropertyData(BeanData bean, BeanGenConfig config, int lineIndex) { this.bean = bean; this.config = config; this.lineIndex = lineIndex; } //----------------------------------------------------------------------- /** * Gets the bean. * @return the bean, not null */ public BeanData getBean() { return bean; } /** * Gets the configuration. * * @return the configuration, not null */ public BeanGenConfig getConfig() { return config; } /** * Sets the configuration. * * @param config the new configuration, not null */ public void setConfig(BeanGenConfig config) { this.config = config; } //----------------------------------------------------------------------- /** * Gets the property line index. * @return the property line index */ public int getLineIndex() { return lineIndex; } /** * Gets the property name. * @return the property name */ public String getPropertyName() { return propertyName; } /** * Sets the property name. * @param propertyName the property name to set */ public void setPropertyName(String propertyName) { this.propertyName = propertyName; } /** * Gets the field name. * @return the field name */ public String getFieldName() { return fieldName; } /** * Sets the field name. * @param fieldName the field name to set */ public void setFieldName(String fieldName) { this.fieldName = fieldName; } /** * Gets the meta field name. * @return the meta field name */ public String getMetaFieldName() { return metaFieldName; } /** * Sets the meta field name. * @param metaFieldName the meta field name to set */ public void setMetaFieldName(String metaFieldName) { this.metaFieldName = metaFieldName; } /** * Gets the upper property name. * @return the upper name */ public String getUpperName() { return upperName; } /** * Sets the upper property name. * @param upperName the upper name to set */ public void setUpperName(String upperName) { this.upperName = upperName; } /** * Gets the type. * @return the type */ public String getType() { return type; } /** * Sets the type. * @param type the type to set */ public void setType(String type) { this.type = type; } /** * Gets the builder type. * @return the type */ public String getBuilderType() { return builderType; } /** * Sets the builder type. * @param builderType the type to set */ public void setBuilderType(String builderType) { this.builderType = builderType; } /** * Gets the field type. * @return the field type */ public String getFieldType() { return fieldType; } /** * Sets the field type. * @param fieldType the field type to set */ public void setFieldType(String fieldType) { this.fieldType = fieldType; } /** * Resolves the field type. */ public void resolveType() { if (getTypeStyle() == null) { setTypeStyle(""); } var fieldType = getFieldType(); var generics = ""; if (fieldType.contains("<")) { generics = fieldType.substring(fieldType.indexOf('<')); } if (getTypeStyle().equals("smart")) { setType(fieldType); } else if (!getTypeStyle().isEmpty()) { if (getTypeStyle().contains("<>")) { setType(getTypeStyle().replace("<>", generics)); } else if (getTypeStyle().contains("<")) { setType(getTypeStyle()); } else { setType(getTypeStyle() + generics); } } else { setType(fieldType); } } /** * Resolves the field builder type. */ public void resolveBuilderType() { if (getBuilderTypeStyle() == null) { setBuilderTypeStyle(""); } var fieldType = getFieldType(); var generics = ""; if (fieldType.contains("<")) { generics = fieldType.substring(fieldType.indexOf('<')); } if (getBuilderTypeStyle().equals("smart")) { setBuilderType(fieldType); } else if (!getBuilderTypeStyle().isEmpty()) { if (getBuilderTypeStyle().contains("<>")) { setBuilderType(getBuilderTypeStyle().replace("<>", generics)); } else if (getBuilderTypeStyle().contains("<")) { setBuilderType(getBuilderTypeStyle()); } else { setBuilderType(getBuilderTypeStyle() + generics); } } else { setBuilderType(fieldType); } } /** * Gets whether the field is declared final. * @return the type */ public boolean isFinal() { return isFinal; } /** * Sets whether the field is declared final. * @param isFinal the field is final flag */ public void setFinal(boolean isFinal) { this.isFinal = isFinal; } /** * Gets the field initializer. * @return the initializer */ public String getInitializer() { return initializer; } /** * Sets the field initializer. * @param initializer the field initializer */ public void setInitializer(String initializer) { this.initializer = initializer; } /** * Gets the alias. * @return the alias */ public String getAlias() { return alias; } /** * Sets the alias. * @param alias the alias */ public void setAlias(String alias) { this.alias = (alias != null && !alias.isEmpty() ? alias : null); } /** * Gets the getter style. * @return the getter style */ public String getGetStyle() { return getStyle; } /** * Sets the getter style. * @param getStyle the getter style to set */ public void setGetStyle(String getStyle) { this.getStyle = getStyle; } /** * Gets the type style. * @return the type style */ public String getTypeStyle() { return typeStyle; } /** * Sets the type style. * @param typeStyle the type style to set */ public void setTypeStyle(String typeStyle) { this.typeStyle = typeStyle; } /** * Gets the type builder type style. * @return the builder type style */ public String getBuilderTypeStyle() { return builderTypeStyle; } /** * Sets the builder type style. * @param builderTypeStyle the builder type style to set */ public void setBuilderTypeStyle(String builderTypeStyle) { this.builderTypeStyle = builderTypeStyle; } /** * Gets the equals hashCode style. * @return the equals hashCode style */ public String getEqualsHashCodeStyle() { return equalsHashCodeStyle; } /** * Sets the equals hashCode style. * @param equalsHashCodeStyle the equals hashCode style */ public void setEqualsHashCodeStyle(String equalsHashCodeStyle) { this.equalsHashCodeStyle = equalsHashCodeStyle; } /** * Resolves the equals hashCode generator. * @param file the file * @param lineIndex the line index */ public void resolveEqualsHashCodeStyle(File file, int lineIndex) { if (equalsHashCodeStyle.equals("smart")) { equalsHashCodeStyle = (bean.isImmutable() ? "field" : "getter"); } if (equalsHashCodeStyle.equals("omit") || equalsHashCodeStyle.equals("getter") || equalsHashCodeStyle.equals("field")) { return; } throw new BeanCodeGenException("Invalid equals/hashCode style: " + equalsHashCodeStyle + " in " + getBean().getTypeRaw() + "." + getPropertyName(), file, lineIndex); } /** * Gets the toString style. * @return the toString style */ public String getToStringStyle() { return toStringStyle; } /** * Sets the toString style. * @param toStringStyle the toString style */ public void setToStringStyle(String toStringStyle) { this.toStringStyle = toStringStyle; } /** * Resolves the toString generator. * @param file the file * @param lineIndex the line index */ public void resolveToStringStyle(File file, int lineIndex) { if (toStringStyle.equals("smart")) { toStringStyle = (bean.isImmutable() ? "field" : "getter"); } if (toStringStyle.equals("omit") || toStringStyle.equals("getter") || toStringStyle.equals("field")) { return; } throw new BeanCodeGenException("Invalid toString style: " + toStringStyle + " in " + getBean().getTypeRaw() + "." + getPropertyName(), file, lineIndex); } /** * Gets the setter style. * @return the setter style */ public String getSetStyle() { return setStyle; } /** * Sets the setter style. * @param setStyle the setter style to set */ public void setSetStyle(String setStyle) { this.setStyle = setStyle; } /** * Gets the override get flag. * @return the setter style */ public boolean isOverrideGet() { return overrideGet; } /** * Sets the override get flag. * @param overrideGet the setter style to set */ public void setOverrideGet(boolean overrideGet) { this.overrideGet = overrideGet; } /** * Gets the override get flag. * @return the setter style */ public boolean isOverrideSet() { return overrideSet; } /** * Sets the override get flag. * @param overrideSet the setter style to set */ public void setOverrideSet(boolean overrideSet) { this.overrideSet = overrideSet; } /** * Gets the validation. * @return the validation */ public String getValidation() { return validation; } /** * Sets the validation. * @param validation the validation to set */ public void setValidation(String validation) { this.validation = validation; } /** * Resolves validation. */ public void resolveValidation() { if (isFinal() && !getInitializer().isEmpty() && getValidation().isEmpty()) { setValidation("notNull"); } } /** * Checks if the property is deprecated. * @return the deprecated flag */ public boolean isDeprecated() { return deprecated; } /** * Sets if the property is deprecated. * @param deprecated the deprecated to set */ public void setDeprecated(boolean deprecated) { this.deprecated = deprecated; } //----------------------------------------------------------------------- /** * Gets the first comment line. * @return the first comment */ public String getFirstComment() { return firstComment; } /** * Sets the first comment line. * @param firstComment the first comment to set */ public void setFirstComment(String firstComment) { this.firstComment = firstComment; } /** * Gets the remaining comments. * @return the remaining comments, not null */ public List getComments() { return comments; } /** * Gets the deprecated comment line. * @return the deprecated comment */ public String getDeprecatedComment() { return deprecatedComment; } /** * Sets the deprecated comment line. * @param deprecatedComment the deprecated comment to set */ public void setDeprecatedComment(String deprecatedComment) { this.deprecatedComment = deprecatedComment; } //----------------------------------------------------------------------- /** * Checks if the property is parameterised with generics. * @return true if generified */ public boolean isGenericParamType() { return type.contains("<"); } /** * Checks if the property is parameterised with generics. * {@code Foo} will return true, {@code Foo will return false}. * @return true if generified */ public boolean isGenericWildcardParamType() { return type.endsWith(""); } /** * Gets the parameterisation of the property. * {@code Foo} will return {@code String}. * @return the generic type, or a blank string if not generic, not null */ public String getGenericParamType() { var pos = type.indexOf("<"); return pos < 0 ? "" : type.substring(pos + 1, type.length() - 1); } /** * Checks if the type is the generic type of the bean. * For example, if the property is of type T or T[] in a bean of Foo[T]. * @return true if matches */ public boolean isBeanGenericType() { var stripped = isArrayType() ? type.substring(0, type.length() - 2) : type; return bean.isTypeGenerifiedBy(stripped); } /** * Checks if the property is generic in some way. * @return true if generic */ public boolean isGeneric() { return isGenericParamType() || isBeanGenericType(); } /** * Gets the raw type of the property without generics. * {@code Foo} will return {@code Foo}. * @return the raw type */ public String getTypeRaw() { var pos = type.indexOf("<"); return (pos < 0 ? type : type.substring(0, pos)); } /** * Gets the raw type of the property. * @return the raw type */ public String getFieldTypeRaw() { var pos = fieldType.indexOf("<"); return (pos < 0 ? fieldType : fieldType.substring(0, pos)); } /** * Gets the generic part of the property type. *

* For example, "{@literal Foo}" will return "{@literal }". * * @return the generic part of the type, not null */ public String getTypeGenerics() { var type = getType(); return type.contains("<") ? type.substring(type.indexOf('<')) : ""; } /** * Gets the generic part of the property type. *

* For example, "{@literal Foo}" will return "String". * * @return the generic part of the type, empty if not generic, not null */ public String getTypeGenericsSimple() { var type = getType(); return type.contains("<") ? type.substring(type.indexOf('<') + 1, type.length() - 1) : ""; } /** * Gets the type of the property, erasing generics attached to the bean. * {@code Foo} will return {@code Foo} where {@code T extends Number}. * @return the raw type */ public String getTypeBeanErased() { if (isBeanGenericType()) { for (var i = 0; i < bean.getTypeGenericCount(); i++) { if (type.equals(bean.getTypeGenericName(i, false))) { return bean.getTypeGenericErased(i); } } } var generic = getTypeGenericsSimple(); if (generic.isEmpty()) { return type; } var tkn = new StringTokenizer(generic, ","); List altered = new ArrayList<>(); while (tkn.hasMoreTokens()) { var genericType = tkn.nextToken().trim(); var erased = genericType; if (bean.isTypeGenerifiedBy(genericType)) { for (var i = 0; i < bean.getTypeGenericCount(); i++) { if (genericType.equals(bean.getTypeGenericName(i, false))) { erased = bean.getTypeGenericErased(i); } } } altered.add(erased); } return getTypeRaw() + "<" + String.join(", ", altered) + ">"; } /** * Checks if the property is derived. * @return true if derived */ public boolean isDerived() { return fieldName == null; } //----------------------------------------------------------------------- /** * Resolves the getter generator. * @param file the file * @param lineIndex the line index */ public void resolveGetterGen(File file, int lineIndex) { if (getGetStyle() == null) { setGetStyle(""); } var style = getGetStyle(); var access = "public"; switch (style) { case "private" -> { style = "smart"; access = "private"; } case "package" -> { style = "smart"; access = "package"; } case "protected" -> { style = "smart"; access = "protected"; } } if (style.equals("get")) { getterGen = GetterGen.GetGetterGen.PUBLIC; } else if (style.equals("is")) { getterGen = GetterGen.IsGetterGen.PUBLIC; } else if (style.equals("smart")) { if (bean.isImmutable()) { var clone = config.getImmutableGetClones().get(getFieldTypeRaw()); if ("clone".equals(clone)) { getterGen = isNotNull() ? GetterGen.CloneNNGetterGen.of(access) : GetterGen.CloneGetterGen.of(access); } else if ("cloneCast".equals(clone)) { getterGen = isNotNull() ? GetterGen.CloneCastNNGetterGen.of(access) : GetterGen.CloneCastGetterGen.of(access); } else if ("cloneArray".equals(clone)) { getterGen = GetterGen.CloneArrayGetterGen.of(access); } else if (getType().equals("boolean")) { getterGen = GetterGen.IsGetterGen.of(access); } else { getterGen = GetterGen.GetGetterGen.of(access); } } else if (getType().equals("boolean")) { getterGen = GetterGen.IsGetterGen.of(access); } else { getterGen = GetterGen.GetGetterGen.of(access); } } else if (style.isEmpty()) { getterGen = GetterGen.NoGetterGen.INSTANCE; } else if (style.equals("field")) { getterGen = GetterGen.NoGetterGen.INSTANCE; } else if (style.equals("clone")) { getterGen = isNotNull() ? GetterGen.CloneNNGetterGen.PUBLIC : GetterGen.CloneGetterGen.PUBLIC; } else if (style.equals("cloneCast")) { getterGen = isNotNull() ? GetterGen.CloneCastNNGetterGen.PUBLIC : GetterGen.CloneCastGetterGen.PUBLIC; } else if (style.equals("cloneArray")) { getterGen = GetterGen.CloneArrayGetterGen.PUBLIC; } else if (style.equals("optional")) { getterGen = GetterGen.Optional8GetterGen.PUBLIC; } else if (style.equals("optionalGuava")) { getterGen = GetterGen.OptionalGuavaGetterGen.PUBLIC; } else if (style.equals("manual")) { getterGen = GetterGen.ManualGetterGen.INSTANCE; } else { throw new BeanCodeGenException("Unable to locate getter generator '" + style + "'" + " in " + getBean().getTypeRaw() + "." + getPropertyName(), file, lineIndex); } } /** * Gets the getter generator. * @return the getter generator */ public GetterGen getGetterGen() { return getterGen; } //----------------------------------------------------------------------- /** * Resolves the setter generator. * @param file the file * @param lineIndex the line index */ public void resolveSetterGen(File file, int lineIndex) { if (getSetStyle() == null) { setSetStyle(""); } var style = getSetStyle().replace("\\n", "\n"); var access = "public"; switch (style) { case "private" -> { style = "smart"; access = "private"; } case "package" -> { style = "smart"; access = "package"; } case "protected" -> { style = "smart"; access = "protected"; } } if (style.equals("set")) { setterGen = SetterGen.SetSetterGen.PUBLIC; } else if (style.equals("setClearAddAll")) { setterGen = new SetterGen.PatternSetterGen("$field.clear();\n$field.addAll($value);"); } else if (style.equals("setClearPutAll")) { setterGen = new SetterGen.PatternSetterGen("$field.clear();\n$field.putAll($value);"); } else if (style.equals("bound")) { if (isFinal()) { throw new IllegalArgumentException("Final field must not have a bound setter"); } else { setterGen = SetterGen.ObservableSetterGen.PUBLIC; bound = true; } } else if (style.equals("cloneArray")) { setterGen = new SetterGen.PatternSetterGen("$field = ($type) JodaBeanUtils.cloneArray($value);"); } else if (style.equals("smart")) { if (isDerived()) { setterGen = SetterGen.NoSetterGen.INSTANCE; } else if (isFinal()) { if (isCollectionType()) { setterGen = new SetterGen.PatternSetterGen("$field.clear();\n$field.addAll($value);", access); } else if (isMapType()) { setterGen = new SetterGen.PatternSetterGen("$field.clear();\n$field.putAll($value);", access); } else { setterGen = SetterGen.NoSetterGen.INSTANCE; } } else { setterGen = SetterGen.SetSetterGen.of(access); } } else if (style.isEmpty()) { setterGen = SetterGen.NoSetterGen.INSTANCE; } else if (style.equals("field")) { setterGen = SetterGen.FieldSetterGen.INSTANCE; } else if (style.equals("manual")) { setterGen = SetterGen.NoSetterGen.INSTANCE; } else if (style.contains("$field") || style.contains("$value")) { if (style.contains("$field") || style.contains("\n")) { setterGen = new SetterGen.PatternSetterGen(style); } else { setterGen = new SetterGen.PatternSetterGen("$field = " + style); } } else { throw new BeanCodeGenException("Unable to locate setter generator '" + style + "'" + " in " + getBean().getTypeRaw() + "." + getPropertyName(), file, lineIndex); } } /** * Gets the setter generator. * @return the setter generator */ public SetterGen getSetterGen() { return setterGen; } /** * Gets the setter scope. * @return the setter scope */ public String getSetterScope() { if (getSetStyle().equals("private")) { return "private"; } return "public"; } /** * Gets whether the property is bound. * @return true if bound */ public boolean isBound() { return bound; } //----------------------------------------------------------------------- /** * Resolves the copy generator. * @param file the file * @param lineIndex the line index */ public void resolveCopyGen(File file, int lineIndex) { if (getBean().isMutable() && !getBean().isBuilderScopeVisible()) { return; // no copying } if (config.getInvalidImmutableTypes().contains(getFieldTypeRaw())) { throw new BeanCodeGenException("Invalid collection type for immutable bean: " + getFieldTypeRaw() + " in " + getBean().getTypeRaw() + "." + getPropertyName(), file, lineIndex); } if (isDerived()) { copyGen = CopyGen.NoCopyGen.INSTANCE; } else { var copier = config.getCopyGenerators().get(getFieldTypeRaw()); if (copier != null) { copyGen = copier; } else { var clone = config.getImmutableGetClones().get(getFieldTypeRaw()); if (clone != null) { if (clone.equals("cloneCast")) { copyGen = PatternCopyGen.CLONE_CAST; } else if (clone.equals("cloneArray")) { copyGen = PatternCopyGen.CLONE_ARRAY; } else { copyGen = PatternCopyGen.CLONE; } } else { copyGen = PatternCopyGen.ASSIGN; } } } } /** * Gets the copy generator. * @return the copy generator */ public CopyGen getCopyGen() { return copyGen; } //----------------------------------------------------------------------- /** * Resolves the copy generator. */ public void resolveBuilderGen() { if (getBean().isMutable()) { if (!getBean().isBuilderScopeVisible() && !getBean().isBeanStyleLightOrMinimal()) { return; // no builder } } if (isDerived()) { builderGen = BuilderGen.NoBuilderGen.INSTANCE; } else { var builder = config.getBuilderGenerators().get(getFieldTypeRaw()); builderGen = Objects.requireNonNullElseGet(builder, BuilderGen.SimpleBuilderGen::new); } } /** * Gets the builder generator. * @return the builder generator */ public BuilderGen getBuilderGen() { return builderGen; } //----------------------------------------------------------------------- /** * Checks if this property is an array type. * * @return true if it is an array type */ public boolean isArrayType() { return getType().endsWith("[]"); } /** * Checks if this property is an array type. * * @return true if it is an array type */ public boolean isGenericArrayType() { return getType().endsWith("[]") && getType().length() == 3; } /** * Checks if this property is a known collection type. * * @return true if it is a known collection type */ public boolean isCollectionType() { return isGeneric() && COLLECTIONS.contains(getTypeRaw()); } /** * Checks if this property is a known set type. * * @return true if it is a known set type */ public boolean isSetType() { return isGeneric() && SETS.contains(getTypeRaw()); } /** * Checks if this property is a known sorted set type. * * @return true if it is a known set type */ public boolean isSortedSetType() { return isGeneric() && SORTED_SETS.contains(getTypeRaw()); } /** * Checks if this property is a known map type. * * @return true if it is a known map type */ public boolean isMapType() { return "FlexiBean".equals(getType()) || (isGeneric() && MAPS.contains(getTypeRaw())); } /** * Gets the read-write flag. * * @return the read write */ public PropertyStyle getStyle() { if (isDerived()) { return PropertyStyle.DERIVED; } if (getBean().isImmutable()) { return PropertyStyle.IMMUTABLE; } if (!getGetStyle().isEmpty() && !getSetStyle().isEmpty() && (getSetterGen().isSetterGenerated(this) || getSetStyle().equals("manual"))) { return PropertyStyle.READ_WRITE; } if (!getGetStyle().isEmpty()) { if (bean.isBuilderScopeVisible()) { return PropertyStyle.READ_ONLY_BUILDABLE; } else { return PropertyStyle.READ_ONLY; } } if (!getSetStyle().isEmpty()) { return PropertyStyle.WRITE_ONLY; } throw new RuntimeException("Property must have a getter or setter: " + getBean().getTypeRaw() + "." + getPropertyName()); } //----------------------------------------------------------------------- /** * Checks if the validation is non-null. * @return true if non-null */ public boolean isValidated() { return getValidation() != null && !getValidation().isEmpty(); } /** * Checks if the validation is non-null. * @return true if non-null */ public boolean isNotNull() { return getValidation().equals("notNull") || getValidation().equals("notEmpty") || getValidation().equals("notBlank"); } /** * Gets the validation non-null Javadoc. * @return the non-null text */ public String getNotNullJavadoc() { return switch (getValidation()) { case "notNull" -> ", not null"; case "notEmpty" -> ", not empty"; case "notBlank" -> ", not blank"; default -> ""; }; } /** * Gets the validation method name. * @return the method name */ public String getValidationMethodName() { if (!isValidated()) { throw new IllegalStateException(); } if (getValidation().equals("notNull") || getValidation().equals("notEmpty") || getValidation().equals("notBlank")) { return "JodaBeanUtils." + getValidation(); } return getValidation(); // method in bean or static } /** * Gets the varargs code. * * @return the varargs code, null if not applicable */ public String getVarArgsCode() { return config.getImmutableVarArgs().get(getTypeRaw()); } } ================================================ FILE: src/main/java/org/joda/beans/gen/PropertyDefinition.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation defining a property for code generation. *

* This annotation must be used on all private instance variables that * should be treated as properties. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface PropertyDefinition { /** * An alternative name for the property. *

* The property can be looked up using the specified alias. * The primary name is unaffected, and the alias is only used in certain circumstances. * For example, {@code bean.metaProperty("alias")} and {@code bean.property("alias")} * will both work, as will getting and setting via an immutable bean builder. *

* This attribute is most useful in handling change from serialized forms. * * @return the alias of the property, defaulted to '' */ String alias() default ""; /** * The style of the method used to query the property. *

* The style is a string describing the getter, typically used for code generation. * By default this is 'smart' which will use the source code knowledge to determine * what to generate. This will be a method of the form {@code isXxx()} for {@code boolean} * and {@code getXxx()} for all other types. *

* Supported style strings are: *

    *
  • '' - do not generate any form of getter *
  • 'smart' - process intelligently - 'is' for boolean and 'get' for other types *
  • 'private' - process as per 'smart' but set scope as private *
  • 'package' - process as per 'smart' but set scope as package/default *
  • 'protected' - process as per 'smart' but set scope as protected *
  • 'is' - generates isXxx() *
  • 'get' - generates getXxx() *
  • 'clone' - generates getXxx() with a clone of the field (assumed to be of the correct type) *
  • 'cloneCast' - generates getXxx() with a clone of the field with a cast to the property type *
  • 'cloneArray' - generates getXxx() with a deep clone of the array suitable for multi-dimensional arrays *
  • 'optional' - generate getXxx() returning a Java 8 {@code Optional} wrapper around the field, * where the field itself is nullable instead of optional. {@code OptionalDouble}, {@code OptionalInt} * and {@code OptionalLong} are also handled *
  • 'optionalGuava' - generate getXxx() returning a Guava {@code Optional} wrapper around the field, * where the field itself is nullable instead of optional *
  • 'field' - generates direct access to the field, enabling a weird manual getter *
  • 'manual' - a method named getXxx() must be manually provided at package scope or greater *
* * @return the getter style, defaulted to 'smart' */ String get() default "smart"; /** * The style of the method used to mutate the property. *

* The style is a string describing the mutator, typically used for code generation. * By default this is 'smart' which will use the source code knowledge to determine * what to generate. This will be a method of the form {@code setXxx()} for all types unless * the field is {@code final}. If the field is a final {@code Collection} or {@code Map} * of a known type then a set method is generated using {@code addAll} or {@code puAll} *

* Standard style strings are: *

    *
  • '' - do not generate any form of setter *
  • 'smart' - process intelligently - uses 'set' unless final, when it will use 'setClearAddAll' * for common list types or 'setClearPutAll' for common map types and FlexiBean *
  • 'private' - process as per 'smart' but set scope as private *
  • 'package' - process as per 'smart' but set scope as package/default *
  • 'protected' - process as per 'smart' but set scope as protected *
  • 'set' - generates setXxx() *
  • 'setClearAddAll' - generates setXxx() using field.clear() and field.addAll(newData) *
  • 'setClearPutAll' - generates setXxx() using field.clear() and field.putAll(newData) *
  • 'cloneArray' - generates setXxx() with a deep clone of the array suitable for multi-dimensional arrays *
  • 'bound' - generates a bound property with {@code PropertyChangeSupport} *
  • 'field' - generates direct access to the field, enabling a weird manual setter *
  • 'manual' - a method named setXxx() must be manually provided at package scope or greater *
  • a pattern, see below *
*

* A pattern can be used for special behaviour. * The pattern is a complete piece of code. * For example, 'new Foo($value)' or '$field = $value.clone()'.
* '$field' for the field to copy into.
* '$value' for the value to copy from.
* '$type' for the type of the field.
* '<>' for the generics of the type including angle brackets.
* '\n' for a new line (all lines must then include semicolons).
* * @return the setter style, defaulted to 'smart' */ String set() default "smart"; /** * Whether the generated getter should be declared with the {@code Override} annotation. *

* By default, the annotation is not added. * * @return true to override the generated get method */ boolean overrideGet() default false; /** * Whether the generated setter should be declared with the {@code Override} annotation. *

* By default, the annotation is not added. * * @return true to override the generated set method */ boolean overrideSet() default false; /** * The exposed type of the property. *

* The style is used to control the exposed type of the property in * getters and setters, or similar. *

* This is used when the type of the field is not the same as the type * that should be used in public methods such as getters and setters. *

* By default, the declared type will be used as the exposed type. * * @return the exposed type, defaulted to 'smart' */ String type() default "smart"; /** * The exposed type of the property in the builder and associated constructor. *

* The style is used to control the exposed type of the property in * immutable builders and associated constructors, or similar. *

* This is used when the type of the field is not the same as the type * that should be used in public methods such as builder setters. *

* By default, the declared type will be used as the exposed type. *

* This is typically used to add '? extends' to collection types. * * @return the builder type, defaulted to 'smart' */ String builderType() default "smart"; /** * The configuration for equals and hash code. *

* This flag controls generation of the {@code equals} and {@code hashCode} methods. * The default is 'smart'. *

* Standard strings are: *

    *
  • 'omit' - omit this property from equals and hashCode *
  • 'smart' - process intelligently, equivalent to 'field' for immutable and 'getter' for mutable *
  • 'getter' - include in equals and hashCode using the getter *
  • 'field' - include in equals and hashCode using the field *
* * @return the equals/hashCode style, defaulted to 'smart' */ String equalsHashCodeStyle() default "smart"; /** * The configuration for toString. *

* This flag controls generation of the {@code toString} method. * The default is 'smart'. *

* Standard strings are: *

    *
  • 'omit' - omit this property from toString *
  • 'smart' - process intelligently, equivalent to 'field' for immutable and 'getter' for mutable *
  • 'getter' - include in toString using the getter *
  • 'field' - include in toString using the field *
* * @return the toString style, defaulted to 'smart' */ String toStringStyle() default "smart"; /** * The validator to use. *

* The property value may be validated by specifying this attribute. * By default no validation is performed. * The code generator places the validation into the set method and ensures that * new objects are validated correctly. *

* Custom validations, are written by writing a static method and referring to it. * For example, {@code public void checkMyValue(Integer val, String propertyName) ...} * The method generally has a {@code void} return, throwing an exception if validation fails. * There must be two arguments, the value and the property name. The value may be the * property type or a superclass (like Object). The property name should be a String. *

* Standard validation strings are: *

    *
  • '' - do not generate any form of validation *
  • 'notNull' - suitable for checking that the value is non-null, * calls JodaBeanUtils.notNull() which throws an IllegalArgumentException *
  • 'notEmpty' - suitable for checking that a string/collection/map is non-null and non-empty, * calls JodaBeanUtils.notEmpty() which throws an IllegalArgumentException *
  • 'notBlank' - suitable for checking that a string is non-null and non-blank, * calls JodaBeanUtils.notBlank() which throws an IllegalArgumentException *
  • '{className}.{staticMethodName}' - a custom validation method, described above *
* * @return the validation, defaulted to '' */ String validate() default ""; } ================================================ FILE: src/main/java/org/joda/beans/gen/PropertyGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.impl.direct.DirectMetaProperty; /** * A property parsed from the source file. */ class PropertyGen { /** The data model of the property. */ private final PropertyData data; /** * Constructor. * @param propData the property data */ PropertyGen(PropertyData propData) { this.data = propData; } //----------------------------------------------------------------------- List generateConstructorAssign(String fromBean) { return data.getCopyGen().generateCopyToImmutable("\t\t", fromBean, data); } //----------------------------------------------------------------------- List generateMetaPropertyConstant() { data.getBean().ensureImport(MetaProperty.class); data.getBean().ensureImport(DirectMetaProperty.class); var list = new ArrayList(); list.add("\t\t/**"); list.add("\t\t * The meta-property for the {@code " + data.getPropertyName() + "} property."); list.add("\t\t */"); if (data.isBeanGenericType()) { list.add("\t\t@SuppressWarnings({\"unchecked\", \"rawtypes\" })"); list.add("\t\tprivate final MetaProperty<" + propertyType() + "> " + data.getMetaFieldName() + " = (DirectMetaProperty) DirectMetaProperty.of" + readWrite() + "("); list.add("\t\t\t\tthis, \"" + data.getPropertyName() + "\", " + data.getBean().getTypeRaw() + ".class, " + actualType() + ");"); } else { var propertyType = propertyType(); if (propertyType.length() == 1) { propertyType = "Object"; } if (data.isGenericParamType()) { list.add("\t\t@SuppressWarnings({\"unchecked\", \"rawtypes\" })"); } list.add("\t\tprivate final MetaProperty<" + propertyType + "> " + data.getMetaFieldName() + " = DirectMetaProperty.of" + readWrite() + "("); list.add("\t\t\t\tthis, \"" + data.getPropertyName() + "\", " + data.getBean().getTypeRaw() + ".class, " + actualType() + ");"); } return list; } List generateMetaPropertyGetCase() { var list = new ArrayList(); list.add("\t\t\t\tcase " + data.getPropertyName().hashCode() + ": // " + data.getPropertyName()); if (data.getAlias() != null) { list.add("\t\t\t\tcase " + data.getAlias().hashCode() + ": // " + data.getAlias() + " (alias)"); } list.add("\t\t\t\t\treturn this." + data.getMetaFieldName() + ";"); return list; } List generateGetter() { return data.getGetterGen().generateGetter(data); } List generateSetter() { return data.getSetterGen().generateSetter("\t", data); } List generateProperty() { data.getBean().ensureImport(Property.class); var list = new ArrayList(); list.add("\t/**"); list.add("\t * Gets the the {@code " + data.getPropertyName() + "} property."); for (var comment : data.getComments()) { list.add("\t * " + comment); } list.add("\t * @return the property, not null"); if (data.getDeprecatedComment() != null) { list.add("\t * " + data.getDeprecatedComment()); } list.add("\t */"); if (data.isDeprecated()) { list.add("\t@Deprecated"); } list.add("\tpublic " + (data.getBean().isTypeFinal() ? "" : "final ") + "Property<" + propertyType() + "> " + data.getPropertyName() + "() {"); list.add("\t\treturn metaBean()." + data.getPropertyName() + "().createProperty(this);"); list.add("\t}"); list.add(""); return list; } List generateMetaProperty() { var list = new ArrayList(); var propertyType = propertyType(); list.add("\t\t/**"); list.add("\t\t * The meta-property for the {@code " + data.getPropertyName() + "} property."); list.add("\t\t * @return the meta-property, not null"); if (data.getDeprecatedComment() != null) { list.add("\t\t * " + data.getDeprecatedComment()); } list.add("\t\t */"); if (data.isDeprecated()) { list.add("\t\t@Deprecated"); } list.add("\t\tpublic " + (data.getBean().isTypeFinal() ? "" : "final ") + "MetaProperty<" + propertyType + "> " + data.getPropertyName() + "() {"); list.add("\t\t\treturn " + data.getMetaFieldName() + ";"); list.add("\t\t}"); list.add(""); return list; } List generatePropertyGetCase() { var list = new ArrayList(); list.add("\t\t\t\tcase " + data.getPropertyName().hashCode() + ": // " + data.getPropertyName()); if (data.getAlias() != null) { list.add("\t\t\t\tcase " + data.getAlias().hashCode() + ": // " + data.getAlias() + " (alias)"); } if (data.getStyle().isReadable()) { list.add("\t\t\t\t\treturn ((" + data.getBean().getTypeWildcard() + ") bean)." + data.getGetterGen().generateGetInvoke(data) + ";"); } else { list.add("\t\t\t\t\tif (quiet) {"); list.add("\t\t\t\t\t\treturn null;"); list.add("\t\t\t\t\t}"); list.add("\t\t\t\t\tthrow new UnsupportedOperationException(\"Property cannot be read: " + data.getPropertyName() + "\");"); } return list; } List generatePropertySetCase() { var list = new ArrayList(); list.add("\t\t\t\tcase " + data.getPropertyName().hashCode() + ": // " + data.getPropertyName()); if (data.getAlias() != null) { list.add("\t\t\t\tcase " + data.getAlias().hashCode() + ": // " + data.getAlias() + " (alias)"); } var setter = data.getSetterGen().generateSetInvoke(data, castObject() + "newValue"); if (data.getStyle().isWritable() && setter != null) { list.add("\t\t\t\t\t((" + data.getBean().getTypeNoExtends() + ") bean)." + setter + ";"); list.add("\t\t\t\t\treturn;"); } else { list.add("\t\t\t\t\tif (quiet) {"); list.add("\t\t\t\t\t\treturn;"); list.add("\t\t\t\t\t}"); list.add("\t\t\t\t\tthrow new UnsupportedOperationException(\"Property cannot be written: " + data.getPropertyName() + "\");"); } return list; } String generateLambdaGetter() { return "b -> b." + data.getGetterGen().generateGetInvoke(data); } String generateLambdaSetter() { var propType = propertyType(data.getTypeBeanErased()); var cast = propType.equals("Object") ? "" : "(" + propType + ") "; return "(b, v) -> b." + data.getSetterGen().generateSetInvoke(data, cast + "v"); } //----------------------------------------------------------------------- boolean isSpecialInit() { return data.getBuilderGen().isSpecialInit(data); } String generateInit() { return data.getBuilderGen().generateInit(data); } List generateBuilderField() { return data.getBuilderGen().generateField("\t\t", data); } List generateBuilderConstructorAssign(String beanToCopyFrom) { return data.getCopyGen().generateCopyToMutable("\t\t\t", data, beanToCopyFrom); } List generateBuilderFieldGet() { var list = new ArrayList(); list.add("\t\t\t\tcase " + data.getPropertyName().hashCode() + ": // " + data.getPropertyName()); if (data.getAlias() != null) { list.add("\t\t\t\tcase " + data.getAlias().hashCode() + ": // " + data.getAlias() + " (alias)"); } list.add("\t\t\t\t\treturn this." + generateBuilderFieldName() + ";"); return list; } List generateBuilderFieldSet() { var list = new ArrayList(); list.add("\t\t\t\tcase " + data.getPropertyName().hashCode() + ": // " + data.getPropertyName()); if (data.getAlias() != null) { list.add("\t\t\t\tcase " + data.getAlias().hashCode() + ": // " + data.getAlias() + " (alias)"); } list.add("\t\t\t\t\tthis." + generateBuilderFieldName() + " = (" + propertyType(getBuilderType()) + ") newValue;"); list.add("\t\t\t\t\tbreak;"); return list; } String generateBuilderFieldName() { return data.getFieldName(); } List generateBuilderSetMethod() { var list = new ArrayList(); list.add("\t\t/**"); list.add("\t\t * Sets " + data.getFirstComment()); for (var comment : data.getComments()) { list.add("\t\t * " + comment); } list.add("\t\t * @param " + data.getPropertyName() + " the new value" + data.getNotNullJavadoc()); list.add("\t\t * @return this, for chaining, not null"); if (data.getDeprecatedComment() != null) { list.add("\t\t * " + data.getDeprecatedComment()); } list.add("\t\t */"); if (data.isDeprecated()) { list.add("\t\t@Deprecated"); } var builderType = getBuilderType(); if (builderType.endsWith("[]") && !builderType.endsWith("[][]") && !builderType.equals("byte[]")) { list.add("\t\tpublic Builder" + data.getBean().getTypeGenericName(true) + " " + data.getPropertyName() + "(" + builderType.substring(0, builderType.length() - 2) + "... " + data.getPropertyName() + ") {"); } else { list.add("\t\tpublic Builder" + data.getBean().getTypeGenericName(true) + " " + data.getPropertyName() + "(" + builderType + " " + data.getPropertyName() + ") {"); } if (data.isValidated()) { list.add("\t\t\t" + data.getValidationMethodName() + "(" + data.getPropertyName() + ", \"" + data.getPropertyName() + "\");"); } list.add("\t\t\tthis." + generateBuilderFieldName() + " = " + data.getPropertyName() + ";"); list.add("\t\t\treturn this;"); list.add("\t\t}"); list.add(""); generateBuilderSetCollectionMethod(list); return list; } String getBuilderType() { return data.getBuilderGen().generateType(data); } private void generateBuilderSetCollectionMethod(List list) { var code = data.getVarArgsCode(); if (code == null) { return; } var argType = data.getTypeGenericsSimple(); if (argType.equals("?")) { argType = "Object"; } if (argType.startsWith("? extends ")) { argType = argType.substring(10); } var safeVarargs = argType.length() == 1 || argType.contains("<"); // generate based on varargs list.add("\t\t/**"); list.add("\t\t * Sets the {@code " + data.getPropertyName() + "} property in the builder"); list.add("\t\t * from an array of objects."); list.add("\t\t * @param " + data.getPropertyName() + " the new value" + data.getNotNullJavadoc()); list.add("\t\t * @return this, for chaining, not null"); if (data.getDeprecatedComment() != null) { list.add("\t\t * " + data.getDeprecatedComment()); } list.add("\t\t */"); if (data.isDeprecated()) { list.add("\t\t@Deprecated"); } if (safeVarargs) { list.add("\t\t@SafeVarargs"); } list.add("\t\tpublic " + (safeVarargs ? "final " : "") + "Builder" + data.getBean().getTypeGenericName(true) + " " + data.getPropertyName() + "(" + argType + "... " + data.getPropertyName() + ") {"); if (code.contains("Arrays.asList")) { data.getBean().ensureImport(Arrays.class); } code = code.replace("$value", data.getPropertyName()); code = code.replace("<>", data.getTypeGenerics()); list.add("\t\t\treturn " + data.getPropertyName() + "(" + code + ");"); list.add("\t\t}"); list.add(""); } //----------------------------------------------------------------------- private String readWrite() { return switch (data.getStyle()) { case READ_WRITE -> "ReadWrite"; case READ_ONLY -> "ReadOnly"; case WRITE_ONLY -> "WriteOnly"; case DERIVED -> "Derived"; case READ_ONLY_BUILDABLE -> "ReadOnlyBuildable"; case IMMUTABLE -> "Immutable"; default -> throw new RuntimeException("Invalid style"); }; } private String actualType() { var pt = propertyType(); if (pt.equals(data.getType())) { var genericStart = pt.indexOf('<'); if (genericStart >= 0) { return "(Class) " + pt.substring(0, genericStart) + ".class"; } if (data.getType().length() == 1) { return "Object.class"; } if (data.isGenericArrayType()) { return "Object[].class"; } return pt + ".class"; } return pt + ".TYPE"; } private String castObject() { var pt = propertyType(); return "(" + pt + ") "; } private String propertyType() { return propertyType(data.getType()); } private String propertyType(String type) { return switch (type) { case "boolean" -> "Boolean"; case "byte" -> "Byte"; case "short" -> "Short"; case "char" -> "Character"; case "int" -> "Integer"; case "long" -> "Long"; case "float" -> "Float"; case "double" -> "Double"; default -> type; }; } PropertyData getData() { return data; } // resolves awkward generics static String resolveWildcard(String input) { return input.equals("") ? "" : input; } } ================================================ FILE: src/main/java/org/joda/beans/gen/PropertyParser.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.regex.Pattern; /** * A property parsed from the source file. */ class PropertyParser { /** The getter pattern. */ private static final Pattern ALIAS_PATTERN = Pattern.compile(".*[ ,(]alias[ ]*[=][ ]*[\"]([a-zA-Z_][a-zA-Z0-9_]*)[\"].*"); /** The getter pattern. */ private static final Pattern GETTER_PATTERN = Pattern.compile(".*[ ,(]get[ ]*[=][ ]*[\"]([a-zA-Z-]*)[\"].*"); /** The setter pattern. */ private static final Pattern SETTER_PATTERN = Pattern.compile(".*[ ,(]set[ ]*[=][ ]*[\"]([ !#-~]*)[\"].*"); /** The override pattern. */ private static final Pattern OVERRIDE_GET_PATTERN = Pattern.compile(".*[ ,(]overrideGet[ ]*[=][ ]*(true|false).*"); /** The override pattern. */ private static final Pattern OVERRIDE_SET_PATTERN = Pattern.compile(".*[ ,(]overrideSet[ ]*[=][ ]*(true|false).*"); /** The type pattern. */ private static final Pattern TYPE_PATTERN = Pattern.compile(".*[ ,(]type[ ]*[=][ ]*[\"]([a-zA-Z0-9 ,_<>?.]*)[\"].*"); /** The type builder pattern. */ private static final Pattern BUILDER_TYPE_PATTERN = Pattern.compile(".*[ ,(]builderType[ ]*[=][ ]*[\"]([a-zA-Z0-9 ,_<>?.]*)[\"].*"); /** The equalsHashCode pattern. */ private static final Pattern EQ_HASH_PATTERN = Pattern.compile(".*[ ,(]equalsHashCodeStyle[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The toString pattern. */ private static final Pattern TO_STR_PATTERN = Pattern.compile(".*[ ,(]toStringStyle[ ]*[=][ ]*[\"]([a-zA-Z]*)[\"].*"); /** The validation pattern. */ private static final Pattern VALIDATION_PATTERN = Pattern.compile(".*[ ,(]validate[ ]*[=][ ]*[\"]([a-zA-Z_.]*)[\"].*"); /** The bean generator. */ private final BeanParser beanParser; /** Annotation line index for {@code PropertyDefinition} in input file. */ private int propertyIndex; /** Annotation line index in input file. */ private int annotationIndex; /** Field line index in input file. */ private int fieldIndex; /** * Constructor. * @param beanParser the bean parser */ PropertyParser(BeanParser beanParser) { this.beanParser = beanParser; } //----------------------------------------------------------------------- PropertyGen parse(BeanData beanData, List content, int lineIndex) { propertyIndex = lineIndex; annotationIndex = parseAnnotationStart(content, lineIndex); fieldIndex = parseCodeIndex(content); var data = new PropertyData(beanData, beanParser.getConfig(), lineIndex); data.setAlias(parseAlias(content)); data.setGetStyle(parseGetStyle(content)); data.setSetStyle(parseSetStyle(content)); data.setOverrideGet(parseOverrideGet(content)); data.setOverrideSet(parseOverrideSet(content)); data.setTypeStyle(parseTypeStyle(content)); data.setBuilderTypeStyle(parseBuilderTypeStyle(content)); data.setEqualsHashCodeStyle(parseEqualsHashCodeStyle(content)); data.setToStringStyle(parseToStringStyle(content)); data.setValidation(parseValidation(content)); data.setDeprecated(parseDeprecated(content)); data.setFieldName(parseFieldName(content)); data.setPropertyName(makePropertyName(data.getFieldName())); data.setUpperName(makeUpperName(data.getPropertyName())); data.setFinal(parseFinal(content)); data.setFieldType(parseFieldType(content)); data.setInitializer(parseFieldInitializer(content)); data.resolveType(); data.resolveBuilderType(); data.resolveValidation(); data.resolveGetterGen(beanParser.getFile(), lineIndex); data.resolveSetterGen(beanParser.getFile(), lineIndex); data.resolveCopyGen(beanParser.getFile(), lineIndex); data.resolveBuilderGen(); data.resolveEqualsHashCodeStyle(beanParser.getFile(), lineIndex); data.resolveToStringStyle(beanParser.getFile(), lineIndex); data.setMetaFieldName(beanParser.getFieldPrefix() + data.getPropertyName()); parseComments(content, data); if (beanData.isBeanStyleLightOrMinimal() && beanData.isMutable() && data.getSetterGen() instanceof SetterGen.NoSetterGen) { throw new IllegalArgumentException("Light and Minimal style beans do not support final fields when mutable"); } return new PropertyGen(data); } PropertyGen parseDerived(BeanData beanData, List content, int lineIndex) { propertyIndex = lineIndex; annotationIndex = parseAnnotationStart(content, lineIndex); fieldIndex = parseCodeIndex(content); var data = new PropertyData(beanData, beanParser.getConfig(), lineIndex); data.setGetStyle("manual"); data.setSetStyle(""); data.setTypeStyle(""); data.setBuilderTypeStyle(""); data.setDeprecated(parseDeprecated(content)); data.setPropertyName(parseMethodNameAsPropertyName(content)); data.setUpperName(makeUpperName(data.getPropertyName())); data.setFieldType(parseMethodType(content)); data.setInitializer(parseFieldInitializer(content)); data.resolveType(); data.resolveBuilderType(); data.resolveValidation(); data.resolveGetterGen(beanParser.getFile(), lineIndex); data.resolveSetterGen(beanParser.getFile(), lineIndex); data.resolveCopyGen(beanParser.getFile(), lineIndex); data.resolveBuilderGen(); data.setMetaFieldName(beanParser.getFieldPrefix() + data.getPropertyName()); parseComments(content, data); return new PropertyGen(data); } private void parseComments(List content, PropertyData data) { var comments = parseComment(content, data.getPropertyName()); data.setFirstComment(comments.get(0)); data.getComments().addAll(comments.subList(1, comments.size())); for (var it = data.getComments().iterator(); it.hasNext(); ) { var comment = it.next(); if (comment.trim().startsWith("@deprecated")) { data.setDeprecatedComment(comment.trim()); data.setDeprecated(true); it.remove(); } } if (data.isDeprecated() && data.getDeprecatedComment() == null) { data.setDeprecatedComment("@deprecated Deprecated"); } } //----------------------------------------------------------------------- private String makePropertyName(String name) { if (name.startsWith(beanParser.getFieldPrefix())) { return name.substring(beanParser.getFieldPrefix().length()); } return name; } private String makeUpperName(String name) { return name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1); } //----------------------------------------------------------------------- private int parseAnnotationStart(List content, int lineIndex) { var currentIndex = lineIndex; while (currentIndex > 0 && content.get(currentIndex - 1).trim().startsWith("@")) { currentIndex = currentIndex - 1; } return currentIndex; } private int parseCodeIndex(List content) { for (var index = propertyIndex; index < content.size(); index++) { var line = content.get(index).trim(); if (!line.startsWith("@")) { if (line.isEmpty() || line.startsWith("//") || (index > propertyIndex && content.get(index - 1).endsWith(","))) { continue; } return index; } } throw new BeanCodeGenException( "Unable to locate field for property at line " + (propertyIndex + 1), beanParser.getFile(), propertyIndex + 1); } private String parseAlias(List content) { var line = content.get(propertyIndex).trim(); var matcher = ALIAS_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return ""; } private String parseGetStyle(List content) { var line = content.get(propertyIndex).trim(); var matcher = GETTER_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseSetStyle(List content) { var line = content.get(propertyIndex).trim(); var matcher = SETTER_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private boolean parseOverrideGet(List content) { var line = content.get(propertyIndex).trim(); var matcher = OVERRIDE_GET_PATTERN.matcher(line); if (matcher.matches()) { return "true".equals(matcher.group(1)); } return false; } private boolean parseOverrideSet(List content) { var line = content.get(propertyIndex).trim(); var matcher = OVERRIDE_SET_PATTERN.matcher(line); if (matcher.matches()) { return "true".equals(matcher.group(1)); } return false; } private String parseTypeStyle(List content) { var line = content.get(propertyIndex).trim(); var matcher = TYPE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseBuilderTypeStyle(List content) { var line = content.get(propertyIndex).trim(); var matcher = BUILDER_TYPE_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseEqualsHashCodeStyle(List content) { var line = content.get(propertyIndex).trim(); var matcher = EQ_HASH_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseToStringStyle(List content) { var line = content.get(propertyIndex).trim(); var matcher = TO_STR_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return "smart"; } private String parseValidation(List content) { var line = content.get(propertyIndex).trim(); var matcher = VALIDATION_PATTERN.matcher(line); if (matcher.matches()) { return matcher.group(1); } return ""; } private boolean parseDeprecated(List content) { for (var index = annotationIndex; index < fieldIndex; index++) { var line = content.get(index).trim(); if (line.equals("@Deprecated") || line.startsWith("@Deprecated ")) { return true; } } return false; } //----------------------------------------------------------------------- private String parseFieldName(List content) { var line = parseFieldDefinition(content); var parts = line.split(" "); var last = parts[parts.length - 1]; if (last.endsWith(";") && last.length() > 1) { return last.substring(0, last.length() - 1); } throw new BeanCodeGenException( "Unable to locate field name at line " + (propertyIndex + 1), beanParser.getFile(), propertyIndex + 1); } private boolean parseFinal(List content) { var line = parseFieldDefinition(content); var parts = line.split(" "); if (parts.length < 2) { throw new BeanCodeGenException( "Unable to locate field type at line " + (propertyIndex + 1), beanParser.getFile(), propertyIndex + 1); } if (parts[0].equals("final") || parts[1].equals("final") || (parts.length >= 3 && parts[2].equals("final"))) { return true; } return false; } private String parseFieldType(List content) { var line = parseFieldDefinition(content); var parts = line.split(" "); if (parts.length < 2) { throw new BeanCodeGenException( "Unable to locate field type at line " + (propertyIndex + 1), beanParser.getFile(), propertyIndex + 1); } var partsPos = parts.length - 2; var type = parts[partsPos]; while (true) { int open = 0, openPos = 0, close = 0, closePos = 0; while ((openPos = type.indexOf('<', openPos)) >= 0) { open++; openPos++; } while ((closePos = type.indexOf('>', closePos)) >= 0) { close++; closePos++; } if (open == close) { break; } if (partsPos == 0) { throw new BeanCodeGenException( "Unable to locate field type at line " + (propertyIndex + 1) + ", mismatched generics", beanParser.getFile(), propertyIndex + 1); } partsPos--; type = parts[partsPos] + " " + type; } return type; } private String parseFieldDefinition(List content) { var line = content.get(fieldIndex).trim(); if (line.contains("//")) { line = line.substring(0, line.indexOf("//")).trim(); } if (line.contains("=")) { line = line.substring(0, line.indexOf("=")).trim() + ";"; } return line.replace(" ", " "); } private String parseFieldInitializer(List content) { var line = content.get(fieldIndex).trim(); if (line.contains("//")) { line = line.substring(0, line.indexOf("//")).trim(); } if (line.contains(" = ")) { line = line.substring(line.indexOf(" = ") + 3).trim(); if (!line.endsWith(";")) { throw new BeanCodeGenException("Field line does not end with semi-colon", beanParser.getFile(), fieldIndex); } return line.substring(0, line.length() - 1).trim(); } return ""; } //----------------------------------------------------------------------- private String parseMethodNameAsPropertyName(List content) { var name = parseMethodDefinition(content)[1]; if (name.isEmpty() || !Character.isUpperCase(name.charAt(0))) { throw new BeanCodeGenException("@DerivedProperty method name invalid: '" + name + "'", beanParser.getFile(), fieldIndex); } return Character.toLowerCase(name.charAt(0)) + name.substring(1); } private String parseMethodType(List content) { var parts = parseMethodDefinition(content); return parts[0]; } private String[] parseMethodDefinition(List content) { var line = content.get(fieldIndex).trim(); if (line.startsWith("public ")) { line = line.substring(7).trim(); } else if (line.startsWith("private ")) { line = line.substring(8).trim(); } else if (line.startsWith("protected ")) { line = line.substring(10).trim(); } var lineEnd = "() {"; if (line.startsWith("abstract ")) { line = line.substring(9).trim(); lineEnd = "();"; } else if (line.startsWith("final ")) { line = line.substring(6).trim(); } else if (line.startsWith("static ")) { throw new BeanCodeGenException("@DerivedProperty method cannot be static", beanParser.getFile(), fieldIndex); } var getIndex = line.indexOf(" get"); if (getIndex < 0) { throw new BeanCodeGenException("@DerivedProperty method must start with 'get'", beanParser.getFile(), fieldIndex); } if (!line.endsWith(lineEnd)) { throw new BeanCodeGenException("@DerivedProperty method must end with '" + lineEnd + "'", beanParser.getFile(), fieldIndex); } line = line.substring(0, line.length() - lineEnd.length()); var split = new String[2]; split[0] = line.substring(0, getIndex).trim(); split[1] = line.substring(getIndex + 4).trim(); return split; } //----------------------------------------------------------------------- private List parseComment(List content, String propertyName) { List comments = new ArrayList<>(); var commentEnd = content.get(annotationIndex - 1).trim(); if (commentEnd.equals("*/")) { var startCommentIndex = -1; for (var index = annotationIndex - 1; index >= 0; index--) { var line = content.get(index).trim(); if (line.equals("/**")) { startCommentIndex = index + 1; break; } } if (startCommentIndex == -1) { throw new BeanCodeGenException("Unable to locate comment start at line " + annotationIndex, beanParser.getFile(), annotationIndex); } if (startCommentIndex < annotationIndex - 1) { for (var i = startCommentIndex; i < annotationIndex - 1; i++) { var commentLine = content.get(i).trim(); if (commentLine.startsWith("*")) { commentLine = commentLine.substring(1).trim(); } if (!commentLine.startsWith("@return") && !commentLine.startsWith("@param") && !commentLine.startsWith("@throws") && !commentLine.startsWith("@exception")) { comments.add(commentLine); } } var firstLine = comments.get(0); if (!firstLine.isEmpty()) { comments.set(0, firstLine.substring(0, 1).toLowerCase(Locale.ENGLISH) + firstLine.substring(1)); } else { comments.remove(0); } } } else if (commentEnd.startsWith("/**") && commentEnd.endsWith("*/")) { var startPos = commentEnd.indexOf("/**") + 3; var endPos = commentEnd.lastIndexOf("*/"); var comment = commentEnd.substring(startPos, endPos).trim(); if (!comment.isEmpty()) { comments.add(comment.substring(0, 1).toLowerCase(Locale.ENGLISH) + comment.substring(1)); } } if (comments.isEmpty()) { comments.add("the " + propertyName + "."); } return comments; } } ================================================ FILE: src/main/java/org/joda/beans/gen/SetterGen.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.gen; import java.util.ArrayList; import java.util.List; /** * A generator of set methods. */ abstract class SetterGen { /** * Checks if a setter method is possible. * * @param prop the property data, not null * @return true if a setter is possible */ abstract boolean isSetterGenerated(PropertyData prop); /** * Generates the setter method. * * @param indent the indent to use, not null * @param prop the property data, not null * @return the generated code, not null */ abstract List generateSetter(String indent, PropertyData prop); /** * Generates the setter method invocation. * This is just the method name. * * @param prop the property data, not null * @param newValue the new value, not null * @return the generated code, null if no setter */ String generateSetInvoke(PropertyData prop, String newValue) { return "set" + prop.getUpperName() + "(" + newValue + ")"; } //----------------------------------------------------------------------- static final class SetSetterGen extends SetterGen { static final SetSetterGen PUBLIC = new SetSetterGen("public "); static final SetSetterGen PROTECTED = new SetSetterGen("protected "); static final SetSetterGen PACKAGE = new SetSetterGen(""); static final SetSetterGen PRIVATE = new SetSetterGen("private "); private final String access; static SetSetterGen of(String access) { return switch (access) { case "private" -> PRIVATE; case "package" -> PACKAGE; case "protected" -> PROTECTED; default -> PUBLIC; }; } private SetSetterGen(String access) { this.access = access; } @Override boolean isSetterGenerated(PropertyData prop) { return true; } @Override List generateSetter(String indent, PropertyData prop) { var list = new ArrayList(); list.add("\t/**"); list.add("\t * Sets " + prop.getFirstComment()); for (var comment : prop.getComments()) { list.add("\t * " + comment); } list.add("\t * @param " + prop.getPropertyName() + " the new value of the property" + prop.getNotNullJavadoc()); if (prop.getDeprecatedComment() != null) { list.add("\t * " + prop.getDeprecatedComment()); } list.add("\t */"); if (prop.isOverrideSet()) { list.add("\t@Override"); } if (prop.isDeprecated()) { list.add("\t@Deprecated"); } list.add("\t" + access + "void set" + prop.getUpperName() + "(" + prop.getType() + " " + prop.getPropertyName() + ") {"); if (prop.isValidated()) { list.add("\t\t" + prop.getValidationMethodName() + "(" + prop.getPropertyName() + ", \"" + prop.getPropertyName() + "\");"); } list.add("\t\tthis." + prop.getFieldName() + " = " + prop.getPropertyName() + ";"); list.add("\t}"); list.add(""); return list; } } static class PatternSetterGen extends SetterGen { private final String setPattern; private final String access; PatternSetterGen(String setPattern) { this(setPattern, "public"); } PatternSetterGen(String setPattern, String access) { this.setPattern = setPattern; this.access = (access.equals("package") ? "" : access + ' '); } @Override boolean isSetterGenerated(PropertyData prop) { return true; } @Override List generateSetter(String indent, PropertyData prop) { var list = new ArrayList(); list.add(indent + "/**"); list.add(indent + " * Sets " + prop.getFirstComment()); for (var comment : prop.getComments()) { list.add(indent + " * " + comment); } list.add(indent + " * @param " + prop.getPropertyName() + " the new value of the property" + prop.getNotNullJavadoc()); if (prop.getDeprecatedComment() != null) { list.add(indent + " * " + prop.getDeprecatedComment()); } list.add(indent + " */"); if (prop.isOverrideSet()) { list.add("\t@Override"); } if (prop.isDeprecated()) { list.add(indent + "@Deprecated"); } list.add(indent + access + "void set" + prop.getUpperName() + "(" + prop.getType() + " " + prop.getPropertyName() + ") {"); if (prop.isValidated()) { list.add("\t\t" + prop.getValidationMethodName() + "(" + prop.getPropertyName() + ", \"" + prop.getPropertyName() + "\");"); } var split = setPattern.split("\n"); for (var line : split) { line = line.replace("$field", "this." + prop.getFieldName()); line = line.replace("$value", prop.getPropertyName()); line = line.replace("$type", prop.getFieldType()); if (split.length == 1 && !line.endsWith(";")) { line += ";"; } list.add(indent + "\t" + line); } list.add(indent + "}"); list.add(""); return list; } } static class NoSetterGen extends SetterGen { static final SetterGen INSTANCE = new NoSetterGen(); @Override boolean isSetterGenerated(PropertyData prop) { return false; } @Override List generateSetter(String indent, PropertyData prop) { return List.of(); } } static class FieldSetterGen extends SetterGen { static final SetterGen INSTANCE = new FieldSetterGen(); @Override boolean isSetterGenerated(PropertyData prop) { return true; } @Override List generateSetter(String indent, PropertyData prop) { return List.of(); } @Override String generateSetInvoke(PropertyData prop, String newValue) { return prop.getFieldName() + " = " + newValue; } } static class ObservableSetterGen extends SetterGen { static final SetterGen PUBLIC = new ObservableSetterGen(); @Override boolean isSetterGenerated(PropertyData prop) { return true; } @Override List generateSetter(String indent, PropertyData prop) { var list = new ArrayList(); list.add("\t/**"); list.add("\t * Sets " + prop.getFirstComment()); for (var comment : prop.getComments()) { list.add("\t * " + comment); } list.add("\t * @param " + prop.getPropertyName() + " the new value of the property" + prop.getNotNullJavadoc()); if (prop.getDeprecatedComment() != null) { list.add("\t * " + prop.getDeprecatedComment()); } list.add("\t */"); if (prop.isOverrideSet()) { list.add("\t@Override"); } if (prop.isDeprecated()) { list.add("\t@Deprecated"); } list.add("\tpublic void set" + prop.getUpperName() + "(" + prop.getType() + " " + prop.getPropertyName() + ") {"); if (prop.isValidated()) { list.add("\t\t" + prop.getValidationMethodName() + "(" + prop.getPropertyName() + ", \"" + prop.getPropertyName() + "\");"); } var old = "old" + prop.getUpperName(); list.add("\t\t" + prop.getFieldType() + " " + old + " = this." + prop.getFieldName() + ";"); list.add("\t\tthis." + prop.getFieldName() + " = " + prop.getPropertyName() + ";"); list.add("\t\tthis." + prop.getConfig().getPrefix() + "propertyChangeSupport.firePropertyChange(\"" + prop.getPropertyName() + "\", " + old + ", " + prop.getPropertyName() + ");"); list.add("\t}"); list.add(""); return list; } } } ================================================ FILE: src/main/java/org/joda/beans/gen/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Code generator for Joda-Beans. *

* The main code generator class is {@code BeanCodeGen}, which is a command line tool. *

* Use of the code generator is optional with Joda-Beans, but it is the most common approach. * The code generator is regenerative. It may be run again and again on the same * file without damaging any changes made in the "user" part of the file. * Only the "code-generated" part of the file will be altered by the generator. */ package org.joda.beans.gen; ================================================ FILE: src/main/java/org/joda/beans/impl/BasicBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; /** * Basic implementation of {@code Bean} intended for applications to subclass. *

* The subclass must provide an implementation for {@link Bean#metaBean()}. * This returns the complete definition of the bean at the meta level. */ public abstract class BasicBean implements Bean { /** * Clones this bean, returning an independent copy. * * @return the clone, not null */ @Override public BasicBean clone() { return JodaBeanUtils.clone(this); } /** * Checks if this bean equals another. *

* This compares the class and all the properties of the bean. * * @param obj the object to compare to, null returns false * @return true if the beans are equal */ @Override public boolean equals(Object obj) { return obj == this || (obj instanceof Bean bean && getClass() == bean.getClass() && JodaBeanUtils.propertiesEqual(this, bean)); } /** * Returns a suitable hash code. *

* The hash code is derived from all the properties of the bean. * * @return a suitable hash code */ @Override public int hashCode() { return getClass().hashCode() ^ JodaBeanUtils.propertiesHashCode(this); } /** * Returns a string that summarises the bean. *

* The string contains the class name and properties. * * @return a summary string, not null */ @Override public String toString() { return JodaBeanUtils.propertiesToString(this, metaBean().beanType().getSimpleName()); } } ================================================ FILE: src/main/java/org/joda/beans/impl/BasicBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; /** * Basic implementation of {@code BeanBuilder} that wraps a real bean. *

* This approach saves creating a temporary map, but is only suitable if the * bean has a no-arg constructor and allows properties to be set. * * @param the bean type */ public class BasicBeanBuilder implements BeanBuilder { /** * The actual target bean. */ private final T bean; /** * Constructs the builder wrapping the target bean. * * @param bean the target bean, not null */ public BasicBeanBuilder(T bean) { this.bean = Objects.requireNonNull(bean, "bean must not be null"); } //----------------------------------------------------------------------- /** * Gets the target bean. * * @return the target bean, not null */ protected T getTargetBean() { return bean; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { return bean.property(propertyName).get(); } @Override public

P get(MetaProperty

metaProperty) { return metaProperty.get(bean); } //----------------------------------------------------------------------- @Override public BeanBuilder set(String propertyName, Object value) { return set(bean.metaBean().metaProperty(propertyName), value); } @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { metaProperty.set(bean, value); return this; } @Override public T build() { validate(bean); return bean; } /** * Hook to allow a subclass to validate the bean. * * @param bean the bean to validate, not null */ protected void validate(T bean) { // override to validate the bean } //----------------------------------------------------------------------- /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder for " + bean.metaBean().beanName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/BasicImmutableBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; /** * Basic implementation of {@code BeanBuilder} that wraps a {@code MetaBean}. *

* The subclass implementation generally has concrete fields for each property. * This class has effectively been replaced by {@link DirectFieldsBeanBuilder}. * It is retained for situations where the builder is being implemented manually. * * @param the bean type */ public abstract class BasicImmutableBeanBuilder implements BeanBuilder { /** * The meta bean. */ private final MetaBean meta; /** * Constructs the builder. * * @param meta the meta-bean, not null */ public BasicImmutableBeanBuilder(MetaBean meta) { this.meta = meta; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { return get(meta.metaProperty(propertyName)); } @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { return (P) get(metaProperty.name()); } //----------------------------------------------------------------------- @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { set(metaProperty.name(), value); return this; } //----------------------------------------------------------------------- /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder"; } } ================================================ FILE: src/main/java/org/joda/beans/impl/BasicMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import org.joda.beans.MetaBean; /** * Basic implementation of {@code MetaBean}. */ public abstract class BasicMetaBean implements MetaBean { /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanType().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/BasicMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import org.joda.beans.MetaProperty; /** * An abstract base meta-property. * * @param

the type of the property content */ public abstract class BasicMetaProperty

implements MetaProperty

{ /** The name of the property. */ private final String name; /** * Constructor. * * @param propertyName the property name, not empty */ protected BasicMetaProperty(String propertyName) { if (propertyName == null || propertyName.isEmpty()) { throw new NullPointerException("propertyName must not be null or empty"); } this.name = propertyName; } //----------------------------------------------------------------------- @Override public String name() { return name; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { return obj instanceof MetaProperty other && name().equals(other.name()) && declaringType().equals(other.declaringType()); } @Override public int hashCode() { return name().hashCode() ^ declaringType().hashCode(); } /** * Returns a string that summarises the meta-property. * * @return a summary string, not null */ @Override public String toString() { return declaringType().getSimpleName() + ":" + name(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/BasicProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; /** * A property that binds a {@code Bean} to a {@code MetaProperty}. *

* This is the standard implementation of a property. * It defers the strategy of getting and setting the value to the meta-property. *

* This implementation is also a map entry to aid performance in maps. * * @param

the type of the property content */ public final class BasicProperty

implements Property

{ /** The bean that the property is bound to. */ private final Bean bean; /** The meta-property that the property is bound to. */ private final MetaProperty

metaProperty; /** * Factory to create a property avoiding duplicate generics. * * @param

the property type * @param bean the bean that the property is bound to, not null * @param metaProperty the meta property, not null * @return the property, not null */ public static

BasicProperty

of(Bean bean, MetaProperty

metaProperty) { return new BasicProperty<>(bean, metaProperty); } /** * Creates a property binding the bean to the meta-property. * * @param bean the bean that the property is bound to, not null * @param metaProperty the meta property, not null */ private BasicProperty(Bean bean, MetaProperty

metaProperty) { this.bean = Objects.requireNonNull(bean, "bean must not be null"); this.metaProperty = Objects.requireNonNull(metaProperty, "metaProperty must not be null"); } //----------------------------------------------------------------------- @SuppressWarnings("unchecked") @Override public B bean() { return (B) bean; } @Override public MetaProperty

metaProperty() { return metaProperty; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { return obj == this || (obj instanceof Property other && metaProperty.equals(other.metaProperty()) && Objects.equals(get(), other.get())); } @Override public int hashCode() { return metaProperty.hashCode() ^ Objects.hashCode(get()); } /** * Returns a string that summarises the property. * * @return a summary string, not null */ @Override public String toString() { return metaProperty + "=" + get(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/BasicPropertyMap.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.Property; /** * A standard map of properties. *

* This is the standard implementation of a map of properties derived from a meta-bean. */ public final class BasicPropertyMap extends AbstractMap> { /** The bean. */ private final Bean bean; /** * Factory to create a property map avoiding duplicate generics. * * @param bean the bean * @return the property map, not null */ public static BasicPropertyMap of(Bean bean) { return new BasicPropertyMap(bean); } /** * Creates a property map. * * @param bean the bean that the property is bound to, not null */ private BasicPropertyMap(Bean bean) { this.bean = Objects.requireNonNull(bean, "bean must not be null"); } //----------------------------------------------------------------------- @Override public int size() { return bean.metaBean().metaPropertyCount(); } @Override public boolean containsKey(Object obj) { return obj instanceof String str && bean.metaBean().metaPropertyExists(str); } @Override public Property get(Object obj) { return containsKey(obj) ? bean.metaBean().metaProperty(obj.toString()).createProperty(bean) : null; } @Override public Set keySet() { return bean.metaBean().metaPropertyMap().keySet(); } @Override public Set>> entrySet() { return new AbstractSet<>() { // TODO: possibly override contains() @Override public int size() { return bean.metaBean().metaPropertyCount(); } @Override public Iterator>> iterator() { var it = bean.metaBean().metaPropertyMap().values().iterator(); return new Iterator<>() { @Override public boolean hasNext() { return it.hasNext(); } @Override public Entry> next() { var meta = it.next(); return Map.entry(meta.name(), BasicProperty.of(bean, meta)); } @Override public void remove() { throw new UnsupportedOperationException("Unmodifiable"); } }; } }; } //----------------------------------------------------------------------- /** * Flattens the contents of this property map to a {@code Map}. *

* The returned map will contain all the properties from the bean with their actual values. * * @return the unmodifiable map of property name to value, not null */ public Map flatten() { return JodaBeanUtils.flatten(bean); } } ================================================ FILE: src/main/java/org/joda/beans/impl/BufferingBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; /** * Implementation of {@code BeanBuilder} that buffers data in a local map. *

* This is useful for cases where the builder data might be manipulated before * the final build. The buffer can be directly mutated. * * @param the bean type */ public class BufferingBeanBuilder implements BeanBuilder { /** * The target meta-bean. */ private final MetaBean metaBean; /** * The buffered data. */ private final ConcurrentMap, Object> buffer = new ConcurrentHashMap<>(); //----------------------------------------------------------------------- /** * Constructs the builder wrapping the target bean. * * @param metaBean the target meta-bean, not null * @return a new untyped builder, not null */ public static BufferingBeanBuilder of(MetaBean metaBean) { return new BufferingBeanBuilder<>(metaBean); } //----------------------------------------------------------------------- /** * Constructs the builder wrapping the target bean. * * @param metaBean the target meta-bean, not null */ public BufferingBeanBuilder(MetaBean metaBean) { this.metaBean = Objects.requireNonNull(metaBean, "metaBean must not be null"); } //----------------------------------------------------------------------- /** * Gets the meta-beans. * * @return the meta-bean, not null */ public MetaBean getMetaBean() { return metaBean; } /** * Gets the buffer holding the state of the builder. *

* The buffer may be mutated. * * @return the mutable buffer, not null */ public ConcurrentMap, Object> getBuffer() { return buffer; } //----------------------------------------------------------------------- /** * Gets the buffered value associated with the specified property name. * * @param propertyName the property name, not null * @return the current value in the builder, null if not found or value is null */ @Override public Object get(String propertyName) { return get(getMetaBean().metaProperty(propertyName)); } /** * Gets the buffered value associated with the specified property name. * * @param metaProperty the meta-property, not null * @return the current value in the builder, null if not found or value is null */ @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { return (P) getBuffer().get(metaProperty); } //----------------------------------------------------------------------- @Override public BeanBuilder set(String propertyName, Object value) { return set(getMetaBean().metaProperty(propertyName), value); } @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { if (value != null) { // ConcurrentHashMap does not allow null values and setting to null is equivalent to not setting getBuffer().put(metaProperty, value); } return this; } @Override public T build() { @SuppressWarnings("unchecked") var builder = (BeanBuilder) getMetaBean().builder(); for (var entry : getBuffer().entrySet()) { builder.set(entry.getKey(), entry.getValue()); } return builder.build(); } //----------------------------------------------------------------------- /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder for " + metaBean.beanName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/RecordBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.lang.invoke.MethodHandles; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; /** * A bean that is implemented using the record language feature. *

* Simply add {@code implements RecordBean} to the record to turn it into a bean. * There is no need to add annotations. Derived properties are not supported. *

* For public records, this is the approach to use:. * {@snippet lang="java": * public static record StringIntPair(String first, int second) implements RecordBean { * } * } *

* For non-public records, this is the approach to use: * {@snippet lang="java": * private static record StringLongPair(String first, long second) implements RecordBean { * static { * RecordBean.register(StringLongPair.class, MethodHandles.lookup()); * } * } * } *

* Note that a public record within a module that doesn't export the record will need to adopt the * non-public approach. * * @param the record bean type * @since 3.0.0 */ public interface RecordBean> extends ImmutableBean { /** * Registers a meta-bean for the specified record. *

* See the class-level Javadoc to understand when this method should be used. *

* Note that this method must only be called once for each class, and never concurrently. * If you follow one of the two patterns in the class-level Javadoc everything will be fine. * * @param the type of the record * @param recordClass the record class, not null * @param lookup the lookup object, granting permission to non-accessible methods * @return the meta-bean * @throws RuntimeException if unable to register the record */ public static MetaBean register(Class recordClass, MethodHandles.Lookup lookup) { JodaBeanUtils.notNull(recordClass, "recordClass"); JodaBeanUtils.notNull(lookup, "lookup"); validateRecordClass(recordClass); var metaBean = new RecordMetaBean<>(recordClass, lookup); MetaBean.register(metaBean); return metaBean; } // Class could be erased, thus we double-check it private static void validateRecordClass(Class recordClass) { if (!recordClass.isRecord()) { throw new IllegalArgumentException( "RecordBean can only be used with records: " + recordClass.getName()); } if (!ImmutableBean.class.isAssignableFrom(recordClass)) { throw new IllegalArgumentException( "RecordBean can only be used with classes that implement ImmutableBean: " + recordClass.getName()); } } //------------------------------------------------------------------------- @Override @SuppressWarnings("unchecked") public default TypedMetaBean metaBean() { return (TypedMetaBean) MetaBean.of(getClass()); } } ================================================ FILE: src/main/java/org/joda/beans/impl/RecordBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import org.joda.beans.BeanBuilder; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaProperty; /** * The RecordBean bean builder. * * @param the record bean type */ final class RecordBeanBuilder implements BeanBuilder { private final RecordMetaBean metaBean; private final Object[] data; RecordBeanBuilder(RecordMetaBean metaBean, Object[] data) { this.metaBean = metaBean; this.data = data; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { return data[metaBean.index(propertyName)]; } @Override public

P get(MetaProperty

metaProperty) { return metaProperty.propertyType().cast(get(metaProperty.name())); } @Override public BeanBuilder set(String propertyName, Object value) { data[metaBean.index(propertyName)] = value; return this; } @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { return set(metaProperty.name(), value); } @Override public T build() { return metaBean.build(data); } /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder: " + metaBean.beanType().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/RecordMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.RecordComponent; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; /** * A meta-bean for beans implemented using the record language feature. * * @param the record bean type */ final class RecordMetaBean extends BasicMetaBean implements TypedMetaBean { private static final MethodType GETTER_METHOD_TYPE = MethodType.methodType(Object.class, Bean.class); private final Class beanType; private final Map> metaPropertyMap; private final MethodHandle constructorHandle; RecordMetaBean(Class beanType, MethodHandles.Lookup lookup) { JodaBeanUtils.notNull(beanType, "beanType"); JodaBeanUtils.notNull(lookup, "lookup"); this.beanType = beanType; var recordComponents = beanType.getRecordComponents(); var paramTypes = new Class[recordComponents.length]; var properties = LinkedHashMap.>newLinkedHashMap(recordComponents.length); for (int i = 0; i < recordComponents.length; i++) { var name = recordComponents[i].getName(); paramTypes[i] = recordComponents[i].getType(); var getterHandle = findGetterHandle(recordComponents[i], lookup); properties.put(name, new RecordMetaProperty(this, recordComponents[i], getterHandle, i)); } try { var constructor = beanType.getDeclaredConstructor(paramTypes); this.constructorHandle = findConstructorHandle(beanType, lookup, constructor); } catch (NoSuchMethodException ex) { throw new IllegalArgumentException("Invalid record", ex); } this.metaPropertyMap = Collections.unmodifiableMap(properties); } // finds the getter handle private MethodHandle findGetterHandle(RecordComponent recordComponent, Lookup lookup) { try { var handle = lookup.unreflect(recordComponent.getAccessor()); return handle.asType(GETTER_METHOD_TYPE); } catch (IllegalAccessException ex) { throw new IllegalArgumentException("Invalid record, method cannot be accessed: " + recordComponent.getName(), ex); } } // finds constructor which matches types exactly private static MethodHandle findConstructorHandle( Class beanType, MethodHandles.Lookup lookup, Constructor constructor) { try { // spreader allows an Object[] to invoke the positional arguments var constructorType = MethodType.methodType(Void.TYPE, constructor.getParameterTypes()); var baseHandle = lookup.findConstructor(beanType, constructorType) .asSpreader(Object[].class, constructor.getParameterTypes().length); // change the return type so caller can use invokeExact() - this is the erased type of T return baseHandle.asType(baseHandle.type().changeReturnType(ImmutableBean.class)); } catch (NoSuchMethodException ex) { throw new IllegalArgumentException("Invalid record, constructor cannot be found: " + beanType.getSimpleName()); } catch (IllegalAccessException ex) { throw new IllegalArgumentException("Invalid record, constructor cannot be accessed: " + beanType.getSimpleName()); } } //------------------------------------------------------------------------- // finds the index of a property int index(String propertyName) { var metaProperty = metaPropertyMap.get(propertyName); if (metaProperty == null) { throw new NoSuchElementException("Unknown property: " + propertyName); } return metaProperty.getConstructorIndex(); } // builds a new instance T build(Object[] data) { try { return (T) constructorHandle.invokeExact(data); } catch (Error ex) { throw ex; } catch (Throwable ex) { throw new IllegalArgumentException( "Bean cannot be created: " + beanName() + " from " + Arrays.toString(data), ex); } } //------------------------------------------------------------------------- @Override public boolean isBuildable() { return true; } @Override public BeanBuilder builder() { var data = new Object[metaPropertyMap.size()]; return new RecordBeanBuilder<>(this, data); } @Override public Class beanType() { return beanType; } @SuppressWarnings({"rawtypes", "unchecked"}) @Override public Map> metaPropertyMap() { return (Map) metaPropertyMap; } } ================================================ FILE: src/main/java/org/joda/beans/impl/RecordMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; import java.lang.reflect.RecordComponent; import java.lang.reflect.Type; import java.util.List; import org.joda.beans.Bean; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.PropertyStyle; import com.google.common.collect.ImmutableList; /** * The RecordBean meta-property. * * @param

the property type */ final class RecordMetaProperty

implements MetaProperty

{ private final MetaBean metaBean; private final RecordComponent recordComponent; private final MethodHandle getterHandle; private final int constructorIndex; RecordMetaProperty( MetaBean metaBean, RecordComponent recordComponent, MethodHandle getterHandle, int constructorIndex) { this.metaBean = metaBean; this.recordComponent = recordComponent; this.getterHandle = getterHandle; this.constructorIndex = constructorIndex; } //------------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public String name() { return recordComponent.getName(); } @Override public Class declaringType() { return recordComponent.getDeclaringRecord(); } @Override @SuppressWarnings("unchecked") public Class

propertyType() { return (Class

) recordComponent.getType(); } @Override public Type propertyGenericType() { return recordComponent.getGenericType(); } @Override public PropertyStyle style() { return PropertyStyle.IMMUTABLE; } @Override public List annotations() { return ImmutableList.copyOf(recordComponent.getAnnotations()); } @Override @SuppressWarnings("unchecked") public P get(Bean bean) { try { return (P) getterHandle.invokeExact(bean); } catch (Throwable ex) { throw new RuntimeException("Property cannot be read: " + name(), ex); } } @Override public void set(Bean bean, Object value) { throw new UnsupportedOperationException("Property cannot be written: " + name()); } //------------------------------------------------------------------------- @Override public boolean equals(Object obj) { return obj instanceof MetaProperty other && name().equals(other.name()) && declaringType().equals(other.declaringType()); } @Override public int hashCode() { return name().hashCode() ^ declaringType().hashCode(); } /** * Returns a string that summarises the meta-property. * * @return a summary string, not null */ @Override public String toString() { return declaringType().getSimpleName() + ":" + name(); } int getConstructorIndex() { return constructorIndex; } } ================================================ FILE: src/main/java/org/joda/beans/impl/StandaloneMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; /** * A meta-property that exists separate from a bean. *

* One use case for this is to handle renamed properties in {@code SerDeserializer}. * * @param

the type of the property content */ public final class StandaloneMetaProperty

extends BasicMetaProperty

{ /** * The meta-bean, which does not have to refer to this property. */ private final MetaBean metaBean; /** * The type of the property. */ private final Class

propertyType; /** * The type of the property. */ private final Type type; //----------------------------------------------------------------------- /** * Creates a non-generified property. * * @param the property type * @param propertyName the property name, not empty * @param metaBean the meta-bean, which does not have to refer to this property, not null * @param propertyType the type of the property, not null * @return the meta-property, not null */ public static StandaloneMetaProperty of(String propertyName, MetaBean metaBean, Class propertyType) { return new StandaloneMetaProperty<>(propertyName, metaBean, propertyType, propertyType); } /** * Creates a property. * * @param the property type * @param propertyName the property name, not empty * @param metaBean the meta-bean, which does not have to refer to this property, not null * @param propertyType the type of the property, not null * @param type the type of the property, not null * @return the meta-property, not null */ public static StandaloneMetaProperty of(String propertyName, MetaBean metaBean, Class propertyType, Type type) { return new StandaloneMetaProperty<>(propertyName, metaBean, propertyType, type); } //----------------------------------------------------------------------- /** * Creates an instance. * * @param propertyName the property name, not empty * @param metaBean the meta-bean, which does not have to refer to this property, not null * @param propertyType the type of the property, not null * @param type the type of the property, not null */ private StandaloneMetaProperty(String propertyName, MetaBean metaBean, Class

propertyType, Type type) { super(propertyName); Objects.requireNonNull(metaBean, "metaBean must not be null"); Objects.requireNonNull(propertyType, "propertyType must not be null"); Objects.requireNonNull(type, "type must not be null"); this.metaBean = metaBean; this.propertyType = propertyType; this.type = type; } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return metaBean().beanType(); } @Override public Class

propertyType() { return propertyType; } @Override public Type propertyGenericType() { return type; } @Override public PropertyStyle style() { return PropertyStyle.READ_WRITE; } //----------------------------------------------------------------------- @Override public List annotations() { return Collections.emptyList(); } //----------------------------------------------------------------------- @Override public P get(Bean bean) { return propertyType.cast(metaBean().metaProperty(name()).get(bean)); } @Override public void set(Bean bean, Object value) { metaBean().metaProperty(name()).set(bean, value); } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import org.joda.beans.Bean; /** * A bean implementation designed for use by the code generator. *

* It used to be mandatory for code generated beans to extend this class. * Now, beans can simply implement the {@code Bean} interface. */ public abstract class DirectBean implements Bean { @Override public abstract DirectBean clone(); } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import org.joda.beans.Bean; import org.joda.beans.impl.BasicBeanBuilder; /** * A builder implementation designed for use by the code generator. *

* This implementation adds validation on top of basic builder functionality. * * @param the bean type */ public class DirectBeanBuilder extends BasicBeanBuilder { /** * Constructs the builder wrapping the target bean. * * @param bean the target bean, not null */ public DirectBeanBuilder(T bean) { super(bean); } //----------------------------------------------------------------------- @Override protected void validate(T bean) { ((DirectMetaBean) bean.metaBean()).validate(bean); } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectFieldsBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; import org.joda.beans.test.JodaBeanTests; /** * A builder implementation designed for use by the code generator. *

* This implementation is intended to have fields generated in the subclass. * * @param the bean type */ public abstract class DirectFieldsBeanBuilder implements BeanBuilder { /** * Constructs the builder. */ protected DirectFieldsBeanBuilder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { throw new UnsupportedOperationException(); } @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { return (P) get(metaProperty.name()); } //----------------------------------------------------------------------- @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { try { set(metaProperty.name(), value); return this; } catch (RuntimeException ex) { if (value == JodaBeanTests.TEST_COVERAGE_STRING) { return this; } throw ex; } } //----------------------------------------------------------------------- /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder"; } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.test.JodaBeanTests; /** * A meta-bean implementation designed for use by the code generator. */ public abstract class DirectMetaBean implements MetaBean { // overriding other methods has negligible effect considering DirectMetaPropertyMap /** * This constant can be used to pass into {@code setString()} to increase test coverage. */ public static final String TEST_COVERAGE_STRING = "!ConstantUsedForTestCoveragePurposes!"; @Override public boolean isBuildable() { return true; } @SuppressWarnings("unchecked") @Override public MetaProperty metaProperty(String propertyName) { var mp = metaPropertyGet(propertyName); if (mp == null) { return metaPropertyNotFound(propertyName); } return (MetaProperty) mp; } @SuppressWarnings("unchecked") private MetaProperty metaPropertyNotFound(String propertyName) { if (propertyName == JodaBeanTests.TEST_COVERAGE_PROPERTY) { // cast is unsafe unless R is String, but code only used in test coverage scenarios return (MetaProperty) StandaloneMetaProperty.of(propertyName, this, String.class); } throw new NoSuchElementException("Unknown property: " + propertyName); } /** * Gets the meta-property by name. *

* This implementation returns null, and must be overridden in subclasses. * * @param propertyName the property name, not null * @return the meta-property, null if not found */ protected MetaProperty metaPropertyGet(String propertyName) { return null; } //------------------------------------------------------------------------- /** * Gets the value of the property. * * @param bean the bean to query, not null * @param propertyName the property name, not null * @param quiet true to return null if unable to read * @return the value of the property, may be null * @throws NoSuchElementException if the property name is invalid */ protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { // used to enable 100% test coverage in beans if (quiet) { return null; } throw new NoSuchElementException("Unknown property: " + propertyName); } /** * Sets the value of the property. * * @param bean the bean to update, not null * @param propertyName the property name, not null * @param value the value of the property, may be null * @param quiet true to take no action if unable to write * @throws NoSuchElementException if the property name is invalid */ protected void propertySet(Bean bean, String propertyName, Object value, boolean quiet) { // used to enable 100% test coverage in beans if (quiet) { return; } throw new NoSuchElementException("Unknown property: " + propertyName); } /** * Validates the values of the properties. * * @param bean the bean to validate, not null * @throws RuntimeException if a property is invalid */ protected void validate(Bean bean) { } /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanType().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; import org.joda.beans.ResolvedType; import org.joda.beans.impl.BasicMetaProperty; /** * A meta-property implementation designed for use by the code generator. *

* This meta-property uses reflection to find the {@code Field} to obtain the annotations. * * @param

the type of the property content */ public final class DirectMetaProperty

extends BasicMetaProperty

{ /** The meta-bean. */ private final MetaBean metaBean; /** The property type. */ private final Class

propertyType; /** The property generic type. */ private final Type propertyGenericType; /** The function to create the resolved type of the property. */ private final Function, ResolvedType> propertyResolvedTypeFn; /** The declaring type. */ private final Class declaringType; /** The field or method implementing the property. */ private final AccessibleObject fieldOrMethod; /** The style. */ private final PropertyStyle style; /** * Factory to create a read-write meta-property avoiding duplicate generics. * * @param

the property type * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the type declaring the property, not null * @param propertyType the property type, not null * @return the property, not null */ public static

DirectMetaProperty

ofReadWrite( MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType) { var field = findField(metaBean, propertyName); return new DirectMetaProperty<>(metaBean, propertyName, declaringType, propertyType, PropertyStyle.READ_WRITE, field); } /** * Factory to create a read-only meta-property avoiding duplicate generics. * * @param

the property type * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the type declaring the property, not null * @param propertyType the property type, not null * @return the property, not null */ public static

DirectMetaProperty

ofReadOnly( MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType) { var field = findField(metaBean, propertyName); return new DirectMetaProperty<>(metaBean, propertyName, declaringType, propertyType, PropertyStyle.READ_ONLY, field); } /** * Factory to create a write-only meta-property avoiding duplicate generics. * * @param

the property type * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the type declaring the property, not null * @param propertyType the property type, not null * @return the property, not null */ public static

DirectMetaProperty

ofWriteOnly( MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType) { var field = findField(metaBean, propertyName); return new DirectMetaProperty<>(metaBean, propertyName, declaringType, propertyType, PropertyStyle.WRITE_ONLY, field); } /** * Factory to create a buildable read-only meta-property avoiding duplicate generics. * * @param

the property type * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the type declaring the property, not null * @param propertyType the property type, not null * @return the property, not null */ public static

DirectMetaProperty

ofReadOnlyBuildable( MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType) { var field = findField(metaBean, propertyName); return new DirectMetaProperty<>(metaBean, propertyName, declaringType, propertyType, PropertyStyle.READ_ONLY_BUILDABLE, field); } /** * Factory to create a derived read-only meta-property avoiding duplicate generics. * * @param

the property type * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the type declaring the property, not null * @param propertyType the property type, not null * @return the property, not null */ public static

DirectMetaProperty

ofDerived( MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType) { var method = findMethod(metaBean, propertyName); return new DirectMetaProperty<>(metaBean, propertyName, declaringType, propertyType, PropertyStyle.DERIVED, method); } /** * Factory to create an immutable meta-property avoiding duplicate generics. * * @param

the property type * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the type declaring the property, not null * @param propertyType the property type, not null * @return the property, not null */ public static

DirectMetaProperty

ofImmutable( MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType) { var field = findField(metaBean, propertyName); return new DirectMetaProperty<>(metaBean, propertyName, declaringType, propertyType, PropertyStyle.IMMUTABLE, field); } private static Field findField(MetaBean metaBean, String propertyName) { Class cls = metaBean.beanType(); while (cls != DirectBean.class && cls != Object.class && cls != null) { try { return cls.getDeclaredField(propertyName); } catch (NoSuchFieldException ex) { try { return cls.getDeclaredField("_" + propertyName); } catch (NoSuchFieldException ex2) { cls = cls.getSuperclass(); } } } return null; } private static AccessibleObject findMethod(MetaBean metaBean, String propertyName) { var methodName = "get" + propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1); Class cls = metaBean.beanType(); while (cls != DirectBean.class && cls != Object.class && cls != null) { try { return cls.getDeclaredMethod(methodName); } catch (NoSuchMethodException ex) { cls = cls.getSuperclass(); } } return findField(metaBean, propertyName); // backwards compatibility } /** * Constructor. * * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty * @param declaringType the declaring type, not null * @param propertyType the property type, not null * @param style the style, not null * @param fieldOrMethod the reflected field or method, not null */ private DirectMetaProperty(MetaBean metaBean, String propertyName, Class declaringType, Class

propertyType, PropertyStyle style, AccessibleObject fieldOrMethod) { super(propertyName); this.metaBean = Objects.requireNonNull(metaBean, "metaBean must not be null"); this.propertyType = Objects.requireNonNull(propertyType, "propertyType must not be null"); this.propertyGenericType = switch (fieldOrMethod) { case Field field -> field.getGenericType(); case Method method -> method.getGenericReturnType(); case null, default -> propertyType; }; this.declaringType = Objects.requireNonNull(declaringType, "declaringType must not be null"); this.style = Objects.requireNonNull(style, "style must not be null"); this.fieldOrMethod = fieldOrMethod; // may be null var beanType = metaBean.beanType(); var resolvedType = ResolvedType.from(propertyGenericType, beanType); this.propertyResolvedTypeFn = !resolvedType.isParameterized() || Modifier.isFinal(beanType.getModifiers()) ? contextClass -> resolvedType : contextClass -> contextClass == beanType ? resolvedType : ResolvedType.from(propertyGenericType, contextClass); } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return declaringType; } @Override public Class

propertyType() { return propertyType; } @Override public Type propertyGenericType() { return propertyGenericType; } @Override public ResolvedType propertyResolvedType(Class contextClass) { return propertyResolvedTypeFn.apply(contextClass); } @Override public PropertyStyle style() { return style; } @Override public A annotation(Class annotationClass) { if (fieldOrMethod == null) { throw new UnsupportedOperationException("Field not found for property: " + name()); } var annotation = fieldOrMethod.getAnnotation(annotationClass); if (annotation == null) { throw new NoSuchElementException("Unknown annotation: " + annotationClass.getName()); } return annotation; } @Override public Optional annotationOpt(Class annotationClass) { return fieldOrMethod == null ? Optional.empty() : Optional.ofNullable(fieldOrMethod.getAnnotation(annotationClass)); } @Override public List annotations() { if (fieldOrMethod == null) { return Collections.emptyList(); } return Arrays.asList(fieldOrMethod.getDeclaredAnnotations()); } //----------------------------------------------------------------------- @SuppressWarnings("unchecked") @Override public P get(Bean bean) { var meta = (DirectMetaBean) bean.metaBean(); return (P) meta.propertyGet(bean, name(), false); } @Override public void set(Bean bean, Object value) { var meta = (DirectMetaBean) bean.metaBean(); meta.propertySet(bean, name(), value, false); } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectMetaPropertyMap.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import java.util.AbstractCollection; import java.util.AbstractSet; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import org.joda.beans.MetaProperty; /** * A map of name to meta-property designed for use by the code generator. *

* This meta-property map implementation is designed primarily for code-generation. * It stores a reference to the meta-bean and the meta-properties. * The meta-properties are accessed using {@link DirectMetaBean#metaPropertyGet(String)}. *

* This class is immutable and thread-safe. */ @SuppressWarnings("rawtypes") public final class DirectMetaPropertyMap implements Map> { /** The meta-bean. */ private final DirectMetaBean metaBean; /** The property names. */ private final Set keys; /** The meta-properties. */ private final Collection> values; /** The map entries. */ private final Set>> entries; /** * Constructor. * * @param metaBean the meta-bean, not null * @param parent the superclass parent, may be null * @param propertyNames the property names, not null */ @SuppressWarnings("unchecked") public DirectMetaPropertyMap(final DirectMetaBean metaBean, DirectMetaPropertyMap parent, String... propertyNames) { this.metaBean = Objects.requireNonNull(metaBean, "metaBean must not be null"); var parentSize = 0; Entry>[] metaProperties; if (parent != null) { parentSize = parent.size(); metaProperties = Arrays.copyOf(((Entries) parent.entries).metaProperties, parentSize + propertyNames.length); } else { metaProperties = new Entry[propertyNames.length]; } for (var i = 0; i < propertyNames.length; i++) { metaProperties[i + parentSize] = Map.entry(propertyNames[i], metaBean.metaPropertyGet(propertyNames[i])); } keys = new Keys(metaProperties); values = new Values(metaProperties); entries = new Entries(metaProperties); } //----------------------------------------------------------------------- @Override public int size() { return keys.size(); } @Override public boolean isEmpty() { return size() == 0; } @SuppressWarnings("unchecked") @Override public MetaProperty get(Object propertyName) { if (propertyName instanceof String propName) { return (MetaProperty) metaBean.metaPropertyGet(propName); } return null; } @Override public boolean containsKey(Object propertyName) { return propertyName instanceof String propName && metaBean.metaPropertyGet(propName) != null; } @Override public boolean containsValue(Object value) { return value instanceof MetaProperty mp && metaBean.metaPropertyGet(mp.name()) != null; } //----------------------------------------------------------------------- @Override public MetaProperty put(String key, MetaProperty value) { throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified"); } @Override public MetaProperty remove(Object key) { throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified"); } @Override public void putAll(Map> m) { throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified"); } @Override public void clear() { throw new UnsupportedOperationException("DirectBean meta-property map cannot be modified"); } //----------------------------------------------------------------------- @Override public Set keySet() { return keys; } @Override public Collection> values() { return values; } @Override public Set>> entrySet() { return entries; } //----------------------------------------------------------------------- /** * Collection implementation for the keys. */ private static final class Keys extends AbstractSet { private final Entry>[] metaProperties; private Keys(Entry>[] metaProperties) { this.metaProperties = metaProperties; } @Override public Iterator iterator() { return new Iterator<>() { private int index; @Override public boolean hasNext() { return index < metaProperties.length; } @Override public String next() { return metaProperties[index++].getKey(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public int size() { return metaProperties.length; } } /** * Collection implementation for the values. */ private static final class Values extends AbstractCollection> { private final Entry>[] metaProperties; private Values(Entry>[] metaProperties) { this.metaProperties = metaProperties; } @Override public Iterator> iterator() { return new Iterator<>() { private int index; @Override public boolean hasNext() { return index < metaProperties.length; } @Override public MetaProperty next() { return metaProperties[index++].getValue(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public int size() { return metaProperties.length; } } /** * Collection implementation for the entries. */ private static final class Entries extends AbstractSet>> { private final Entry>[] metaProperties; private Entries(Entry>[] metaProperties) { this.metaProperties = metaProperties; } @Override public Iterator>> iterator() { return new Iterator<>() { private int index; @Override public boolean hasNext() { return index < metaProperties.length; } @Override public Entry> next() { return metaProperties[index++]; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public int size() { return metaProperties.length; } } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/DirectPrivateBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; import org.joda.beans.test.JodaBeanTests; /** * A builder implementation designed for use by the code generator. *

* This implementation is intended to have fields generated in the subclass. * * @param the bean type */ public abstract class DirectPrivateBeanBuilder implements BeanBuilder { /** * Constructs the builder. */ protected DirectPrivateBeanBuilder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { throw new UnsupportedOperationException(); } @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { return (P) get(metaProperty.name()); } //----------------------------------------------------------------------- @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { try { set(metaProperty.name(), value); return this; } catch (RuntimeException ex) { if (value == JodaBeanTests.TEST_COVERAGE_STRING) { return this; } throw ex; } } //----------------------------------------------------------------------- /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder"; } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/MinimalMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; /** * A meta-bean implementation designed for use by the code generator. * * @param the type of the bean */ public final class MinimalMetaBean implements TypedMetaBean { /** The bean type. */ private final Class beanType; /** The constructor to use. */ private final Supplier> builderSupplier; /** The meta-property instances of the bean. */ private final Map> metaPropertyMap; /** The aliases. */ private final Map aliasMap; /** * Obtains an instance of the meta-bean for immutable beans. *

* The properties will be determined using reflection to find the * {@link PropertyDefinition} annotation. * The field names must be specified as reflection does not return fields in source code order. * * @param the type of the bean * @param beanType the bean type, not null * @param fieldNames the field names, not null * @param builderSupplier the supplier of bean builders, not null * @param getters the getter functions, not null * @return the meta-bean, not null */ @SafeVarargs public static MinimalMetaBean of( Class beanType, String[] fieldNames, Supplier> builderSupplier, Function... getters) { Objects.requireNonNull(getters, "getters must not be null"); return new MinimalMetaBean<>(beanType, fieldNames, builderSupplier, Arrays.asList(getters), null); } /** * Obtains an instance of the meta-bean for mutable beans. *

* The properties will be determined using reflection to find the * {@link PropertyDefinition} annotation. * The field names must be specified as reflection does not return fields in source code order. * * @param the type of the bean * @param beanType the bean type, not null * @param fieldNames the field names, not null * @param builderSupplier the supplier of bean builders, not null * @param getters the getter functions, not null * @param setters the setter functions, not null * @return the meta-bean, not null */ public static MinimalMetaBean of( Class beanType, String[] fieldNames, Supplier> builderSupplier, List> getters, List> setters) { Objects.requireNonNull(getters, "getters must not be null"); Objects.requireNonNull(setters, "setters must not be null"); return new MinimalMetaBean<>(beanType, fieldNames, builderSupplier, getters, setters); } /** * Constructor. * * @param beanType the bean type, not null * @param builderSupplier the supplier of bean builders, not null * @param fieldNames the field names, not null * @param getters the getter functions, not null * @param setters the setter functions, may be null */ private MinimalMetaBean( Class beanType, String[] fieldNames, Supplier> builderSupplier, List> getters, List> setters) { Objects.requireNonNull(beanType, "beanType must not be null"); Objects.requireNonNull(builderSupplier, "builderSupplier must not be null"); Objects.requireNonNull(fieldNames, "fieldNames must not be null"); Objects.requireNonNull(getters, "getters must not be null"); if (fieldNames.length != getters.size()) { throw new IllegalArgumentException("Number of getter functions must match number of fields"); } if (setters != null && fieldNames.length != setters.size()) { throw new IllegalArgumentException("Number of setter functions must match number of fields"); } this.beanType = beanType; this.builderSupplier = builderSupplier; // extract fields and match to getters/setters var map = new LinkedHashMap>(); for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; Field field; try { field = beanType.getDeclaredField(fieldName); } catch (NoSuchFieldException ex) { throw new IllegalArgumentException(ex); } if (Modifier.isStatic(field.getModifiers())) { throw new IllegalArgumentException("Field must not be static"); } if (field.getAnnotation(PropertyDefinition.class) == null) { throw new IllegalArgumentException("Field must have PropertyDefinition annotation"); } map.put(fieldName, new MinimalMetaProperty<>( this, fieldName, field, getters.get(i), setters != null ? setters.get(i) : null)); } // derived var methods = beanType.getDeclaredMethods(); for (var method : methods) { if (!Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers()) && method.getAnnotation(DerivedProperty.class) != null && method.getName().startsWith("get") && method.getName().length() > 3 && Character.isUpperCase(method.getName().charAt(3)) && method.getParameterTypes().length == 0) { var methodName = method.getName(); var propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); var mp = new MinimalMetaProperty<>(this, method, propertyName); map.put(propertyName, mp); } } this.metaPropertyMap = Collections.unmodifiableMap(map); this.aliasMap = new HashMap<>(); } private MinimalMetaBean( Class beanType, Supplier> builderSupplier, Map> metaPropertyMap, Map aliasMap) { this.beanType = beanType; this.builderSupplier = builderSupplier; this.metaPropertyMap = metaPropertyMap; this.aliasMap = aliasMap; } //----------------------------------------------------------------------- /** * Adds an alias to the meta-bean. *

* When using {@link #metaProperty(String)}, the alias will return the * meta-property of the real name. * * @param alias the alias * @param realName the real name * @return the new meta-bean instance * @throws IllegalArgumentException if the realName is invalid */ public MinimalMetaBean withAlias(String alias, String realName) { if (!metaPropertyMap.containsKey(realName)) { throw new IllegalArgumentException("Invalid property name: " + realName); } var aliasMap = new HashMap<>(this.aliasMap); aliasMap.put(alias, realName); return new MinimalMetaBean<>(beanType, builderSupplier, metaPropertyMap, aliasMap); } //----------------------------------------------------------------------- @Override public boolean isBuildable() { return true; } @Override public BeanBuilder builder() { return builderSupplier.get(); } @Override public Class beanType() { return beanType; } @Override @SuppressWarnings("unchecked") public MetaProperty metaProperty(String propertyName) { var mp = metaPropertyMap().get(aliasMap.getOrDefault(propertyName, propertyName)); if (mp == null) { throw new NoSuchElementException("Unknown property: " + propertyName); } return (MetaProperty) mp; } @Override public Map> metaPropertyMap() { return metaPropertyMap; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { return obj instanceof MinimalMetaBean other && this.beanType.equals(other.beanType); } @Override public int hashCode() { return beanType.hashCode() + 3; } /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/MinimalMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.direct; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; import org.joda.beans.ResolvedType; import org.joda.beans.impl.BasicMetaProperty; /** * An immutable meta-property based on a functional interface. * * @param

the type of the property content */ final class MinimalMetaProperty

extends BasicMetaProperty

{ /** The meta-bean. */ private final MetaBean metaBean; /** The type of the property. */ private final Class

propertyType; /** The type of the property. */ private final Type propertyGenericType; /** The function to create the resolved type of the property. */ private final Function, ResolvedType> propertyResolvedTypeFn; /** The annotations. */ private final List annotations; /** The read method. */ private final Function getter; /** The write method. */ private final BiConsumer setter; /** The property style. */ private final PropertyStyle style; //----------------------------------------------------------------------- /** * Creates an instance from a {@code Field}. * * @param metaBean the meta bean, not null * @param propertyName the property name, not empty * @param field the field, not null * @param getter the property getter, not null * @param setter the property setter, null if read only */ @SuppressWarnings("unchecked") MinimalMetaProperty( MetaBean metaBean, String propertyName, Field field, Function getter, BiConsumer setter) { super(propertyName); this.metaBean = metaBean; this.propertyType = (Class

) field.getType(); this.propertyGenericType = field.getGenericType(); this.annotations = Arrays.asList(field.getAnnotations()); this.getter = (Function) getter; this.setter = (BiConsumer) setter; if (ImmutableBean.class.isAssignableFrom(metaBean.beanType())) { this.style = PropertyStyle.IMMUTABLE; } else { this.style = setter != null ? PropertyStyle.READ_WRITE : PropertyStyle.READ_ONLY; } this.propertyResolvedTypeFn = createResolvedTypeFunction(); } /** * Creates an instance from a derived {@code Method}. * * @param metaBean the meta bean, not null * @param method the method, not null * @param propertyName the property name, not empty */ @SuppressWarnings("unchecked") MinimalMetaProperty( MetaBean metaBean, Method method, String propertyName) { super(propertyName); this.metaBean = metaBean; this.propertyType = (Class

) method.getReturnType(); this.propertyGenericType = method.getGenericReturnType(); this.annotations = Arrays.asList(method.getAnnotations()); this.getter = b -> { try { return method.invoke(b); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } }; this.setter = null; this.style = PropertyStyle.DERIVED; this.propertyResolvedTypeFn = createResolvedTypeFunction(); } private Function, ResolvedType> createResolvedTypeFunction() { var beanType = metaBean.beanType(); var resolvedType = ResolvedType.from(propertyGenericType, beanType); return !resolvedType.isParameterized() || Modifier.isFinal(beanType.getModifiers()) ? contextClass -> resolvedType : contextClass -> contextClass == beanType ? resolvedType : ResolvedType.from(propertyGenericType, contextClass); } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return metaBean.beanType(); } @Override public Class

propertyType() { return propertyType; } @Override public Type propertyGenericType() { return propertyGenericType; } @Override public ResolvedType propertyResolvedType(Class contextClass) { return propertyResolvedTypeFn.apply(contextClass); } @Override public PropertyStyle style() { return style; } @Override public List annotations() { return annotations; } //----------------------------------------------------------------------- @Override @SuppressWarnings("unchecked") public P get(Bean bean) { try { return (P) getter.apply(bean); } catch (RuntimeException | Error ex) { throw ex; } catch (Throwable ex) { throw new RuntimeException(ex); } } @Override public void set(Bean bean, Object value) { if (setter == null) { throw new UnsupportedOperationException("Property cannot be written: " + name()); } try { setter.accept(bean, value); } catch (RuntimeException | Error ex) { throw ex; } catch (Throwable ex) { throw new RuntimeException(ex); } } } ================================================ FILE: src/main/java/org/joda/beans/impl/direct/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of Joda-Beans designed for extension by the code generator. *

* Use of the code generator is optional with Joda-Beans, but it is the most common approach. * These class are used by the generator, but could potentially be used without it. */ package org.joda.beans.impl.direct; ================================================ FILE: src/main/java/org/joda/beans/impl/flexi/FlexiBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.flexi; import java.io.ObjectStreamException; import java.io.Serial; import java.io.Serializable; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.regex.Pattern; import org.joda.beans.DynamicBean; import org.joda.beans.DynamicMetaBean; import org.joda.beans.Property; import org.joda.beans.impl.BasicProperty; /** * Implementation of a fully dynamic {@code Bean}. *

* Properties are dynamic, and can be added and removed at will from the map. * The internal storage is created lazily to allow a flexi-bean to be used as * a lightweight extension to another bean. *

* Each flexi-bean has a different set of properties. * As such, there is one instance of meta-bean for each flexi-bean. *

* The keys of a flexi-bean must be simple identifiers as per '[a-zA-Z_][a-zA-Z0-9_]*'. */ public final class FlexiBean implements DynamicBean, Serializable { // Alternate way to implement this would be to create a list/map of real property // objects which could then be properly typed /** Serialization version. */ @Serial private static final long serialVersionUID = 1L; /** Valid regex for keys. */ private static final Pattern VALID_KEY = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*"); /** The meta-bean. */ private final transient FlexiMetaBean metaBean = new FlexiMetaBean(this); // CSIGNORE /** The underlying data. */ volatile Map data = Collections.emptyMap();// CSIGNORE //----------------------------------------------------------------------- /** * Creates a standalone meta-bean. *

* This creates a new instance each time in line with dynamic bean principles. * * @return the meta-bean, not null */ public static DynamicMetaBean meta() { return new FlexiBean().metaBean(); } //----------------------------------------------------------------------- /** * Constructor. */ public FlexiBean() { } /** * Constructor that copies all the data entries from the specified bean. * * @param copyFrom the bean to copy from, not null */ public FlexiBean(FlexiBean copyFrom) { putAll(copyFrom.data); } // resolve to set up transient field private Object readResolve() throws ObjectStreamException { return new FlexiBean(this); } //----------------------------------------------------------------------- /** * Gets the internal data map. * * @return the data, not null */ private Map dataWritable() { if (data == Collections.EMPTY_MAP) { data = new LinkedHashMap<>(); } return data; } //----------------------------------------------------------------------- /** * Gets the number of properties. * * @return the number of properties */ public int size() { return data.size(); } /** * Checks if the bean contains a specific property. * * @param propertyName the property name, null returns false * @return true if the bean contains the property */ public boolean contains(String propertyName) { return propertyExists(propertyName); } /** * Gets the value of the property. *

* This returns null if the property does not exist. * * @param propertyName the property name, not empty * @return the value of the property, may be null */ public Object get(String propertyName) { return data.get(propertyName); } /** * Gets the value of the property cast to a specific type. *

* This returns null if the property does not exist. * * @param the value type * @param propertyName the property name, not empty * @param type the type to cast to, not null * @return the value of the property, may be null * @throws ClassCastException if the type is incorrect */ public T get(String propertyName, Class type) { return type.cast(get(propertyName)); } /** * Gets the value of the property as a {@code String}. * This will use {@link Object#toString()}. *

* This returns null if the property does not exist. * * @param propertyName the property name, not empty * @return the value of the property, may be null */ public String getString(String propertyName) { var obj = get(propertyName); return obj != null ? obj.toString() : null; } /** * Gets the value of the property as a {@code boolean}. * * @param propertyName the property name, not empty * @return the value of the property * @throws ClassCastException if the value is not compatible * @throws NullPointerException if the property does not exist or is null */ public boolean getBoolean(String propertyName) { return (Boolean) get(propertyName); } /** * Gets the value of the property as a {@code int}. * * @param propertyName the property name, not empty * @return the value of the property * @throws ClassCastException if the value is not compatible * @throws NullPointerException if the property does not exist or is null */ public int getInt(String propertyName) { return ((Number) get(propertyName)).intValue(); } /** * Gets the value of the property as a {@code int} using a default value. * * @param propertyName the property name, not empty * @param defaultValue the default value for null or invalid property * @return the value of the property * @throws ClassCastException if the value is not compatible */ public int getInt(String propertyName, int defaultValue) { var obj = get(propertyName); return obj != null ? ((Number) obj).intValue() : defaultValue; } /** * Gets the value of the property as a {@code long}. * * @param propertyName the property name, not empty * @return the value of the property * @throws ClassCastException if the value is not compatible * @throws NullPointerException if the property does not exist or is null */ public long getLong(String propertyName) { return ((Number) get(propertyName)).longValue(); } /** * Gets the value of the property as a {@code long} using a default value. * * @param propertyName the property name, not empty * @param defaultValue the default value for null or invalid property * @return the value of the property * @throws ClassCastException if the value is not compatible */ public long getLong(String propertyName, long defaultValue) { var obj = get(propertyName); return obj != null ? ((Number) obj).longValue() : defaultValue; } /** * Gets the value of the property as a {@code double}. * * @param propertyName the property name, not empty * @return the value of the property * @throws ClassCastException if the value is not compatible * @throws NullPointerException if the property does not exist or is null */ public double getDouble(String propertyName) { return ((Number) get(propertyName)).doubleValue(); } /** * Gets the value of the property as a {@code double} using a default value. * * @param propertyName the property name, not empty * @param defaultValue the default value for null or invalid property * @return the value of the property * @throws ClassCastException if the value is not compatible */ public double getDouble(String propertyName, double defaultValue) { var obj = get(propertyName); return obj != null ? ((Number) obj).doubleValue() : defaultValue; } //----------------------------------------------------------------------- /** * Sets a property in this bean to the specified value. *

* This creates a property if one does not exist. * * @param propertyName the property name, not empty * @param newValue the new value, may be null * @return {@code this} for chaining, not null */ public FlexiBean append(String propertyName, Object newValue) { put(propertyName, newValue); return this; } /** * Sets a property in this bean to the specified value. *

* This creates a property if one does not exist. * * @param propertyName the property name, not empty * @param newValue the new value, may be null */ public void set(String propertyName, Object newValue) { put(propertyName, newValue); } /** * Sets a property in this bean to the specified value. *

* This creates a property if one does not exist. * * @param propertyName the property name, not empty * @param newValue the new value, may be null * @return the old value of the property, may be null */ public Object put(String propertyName, Object newValue) { if (!VALID_KEY.matcher(propertyName).matches()) { throw new IllegalArgumentException("Invalid key for FlexiBean: " + propertyName); } return dataWritable().put(propertyName, newValue); } /** * Puts the properties in the specified map into this bean. *

* This creates properties if they do not exist. * * @param map the map of properties to add, not null */ public void putAll(Map map) { if (!map.isEmpty()) { for (var key : map.keySet()) { if (!VALID_KEY.matcher(key).matches()) { throw new IllegalArgumentException("Invalid key for FlexiBean: " + key); } } if (data == Collections.EMPTY_MAP) { data = new LinkedHashMap<>(map); } else { data.putAll(map); } } } /** * Puts the properties in the specified bean into this bean. *

* This creates properties if they do not exist. * * @param other the map of properties to add, not null */ public void putAll(FlexiBean other) { if (other.size() > 0) { if (data == Collections.EMPTY_MAP) { data = new LinkedHashMap<>(other.data); } else { data.putAll(other.data); } } } /** * Removes a property. *

* No error occurs if the property does not exist. * * @param propertyName the property name, not empty */ public void remove(String propertyName) { propertyRemove(propertyName); } /** * Removes all properties. */ public void clear() { if (data != Collections.EMPTY_MAP) { data.clear(); } } //----------------------------------------------------------------------- /** * Checks if the property exists. * * @param propertyName the property name, not empty * @return true if the property exists */ public boolean propertyExists(String propertyName) { return data.containsKey(propertyName); } /** * Gets the value of the property. * * @param propertyName the property name, not empty * @return the value of the property, may be null */ public Object propertyGet(String propertyName) { if (!propertyExists(propertyName)) { throw new NoSuchElementException("Unknown property: " + propertyName); } return data.get(propertyName); } /** * Sets the value of the property. * * @param propertyName the property name, not empty * @param newValue the new value of the property, may be null */ public void propertySet(String propertyName, Object newValue) { put(propertyName, newValue); } //----------------------------------------------------------------------- @Override public DynamicMetaBean metaBean() { return metaBean; } @Override public Property property(String name) { return BasicProperty.of(this, FlexiMetaProperty.of(metaBean, name)); } @Override public Set propertyNames() { return data.keySet(); } @Override public void propertyDefine(String propertyName, Class propertyType) { if (!propertyExists(propertyName)) { put(propertyName, null); } } @Override public void propertyRemove(String propertyName) { if (data != Collections.EMPTY_MAP) { data.remove(propertyName); } } //----------------------------------------------------------------------- /** * Returns a map representing the contents of the bean. * * @return a map representing the contents of the bean, not null */ public Map toMap() { if (size() == 0) { return Collections.emptyMap(); } // retain order, Map.of() does not respect order return Collections.unmodifiableMap(new LinkedHashMap<>(data)); } //----------------------------------------------------------------------- /** * Clones this bean, returning an independent copy. * * @return the clone, not null */ @Override public FlexiBean clone() { return new FlexiBean(this); } /** * Compares this bean to another based on the property names and content. * * @param obj the object to compare to, null returns false * @return true if equal */ @Override public boolean equals(Object obj) { return obj == this || (obj instanceof FlexiBean other && this.data.equals(other.data)); } /** * Returns a suitable hash code. * * @return a hash code */ @Override public int hashCode() { return data.hashCode(); } /** * Returns a string that summarises the bean. *

* The string contains the class name and properties. * * @return a summary string, not null */ @Override public String toString() { return getClass().getSimpleName() + data.toString(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/flexi/FlexiBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.flexi; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; /** * Implementation of a meta-bean for {@code FlexiBean}. */ class FlexiBeanBuilder implements BeanBuilder { /** * The bean itself. */ private final FlexiBean bean; /** * Creates the meta-bean. * * @param bean the underlying bean, not null */ FlexiBeanBuilder(FlexiBean bean) { this.bean = bean; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { // lenient getter return bean.get(propertyName); } @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { // this approach allows meta-property from one bean to be used with another return (P) bean.get(metaProperty.name()); } //----------------------------------------------------------------------- @Override public FlexiBeanBuilder set(String propertyName, Object value) { bean.put(propertyName, value); return this; } @Override public FlexiBeanBuilder set(MetaProperty metaProperty, Object value) { // this approach allows meta-property from one bean to be used with another bean.put(metaProperty.name(), value); return this; } @Override public FlexiBean build() { return bean; } //----------------------------------------------------------------------- @Override public String toString() { return "FlexiBeanBuilder"; } } ================================================ FILE: src/main/java/org/joda/beans/impl/flexi/FlexiMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.flexi; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.DynamicMetaBean; import org.joda.beans.MetaProperty; /** * Implementation of a meta-bean for {@code FlexiBean}. */ class FlexiMetaBean implements DynamicMetaBean { /** * The bean itself. */ private final FlexiBean bean; /** * Creates the meta-bean. * * @param bean the underlying bean, not null */ FlexiMetaBean(FlexiBean bean) { this.bean = bean; } //----------------------------------------------------------------------- @Override public boolean isBuildable() { return true; } @Override public BeanBuilder builder() { return new FlexiBeanBuilder(bean); } @Override public Class beanType() { return FlexiBean.class; } @Override public int metaPropertyCount() { return bean.size(); } @Override public boolean metaPropertyExists(String name) { return bean.propertyExists(name); } @Override public MetaProperty metaProperty(String name) { // do not check if exists return FlexiMetaProperty.of(this, name); } @Override public Iterable> metaPropertyIterable() { if (bean.data.isEmpty()) { return Collections.emptySet(); } return () -> { var it = bean.data.keySet().iterator(); return new Iterator<>() { @Override public boolean hasNext() { return it.hasNext(); } @Override public MetaProperty next() { return FlexiMetaProperty.of(FlexiMetaBean.this, it.next()); } @Override public void remove() { throw new UnsupportedOperationException("Unmodifiable"); } }; }; } @Override public Map> metaPropertyMap() { if (bean.data.isEmpty()) { return Collections.emptyMap(); } var keySet = bean.data.keySet(); var map = LinkedHashMap.>newLinkedHashMap(keySet.size()); for (var name : keySet) { map.put(name, FlexiMetaProperty.of(this, name)); } return Collections.unmodifiableMap(map); } //----------------------------------------------------------------------- @Override public void metaPropertyDefine(String propertyName, Class propertyType) { bean.propertyDefine(propertyName, propertyType); } @Override public void metaPropertyRemove(String propertyName) { bean.propertyRemove(propertyName); } @Override public List annotations() { return Collections.emptyList(); } /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanType().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/flexi/FlexiMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.flexi; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.List; import org.joda.beans.Bean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; import org.joda.beans.impl.BasicMetaProperty; /** * A meta-property using a {@code FlexiBean} for storage. */ final class FlexiMetaProperty extends BasicMetaProperty { /** The meta-bean. */ private final MetaBean metaBean; /** * Factory to create a meta-property. * * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty */ static FlexiMetaProperty of(MetaBean metaBean, String propertyName) { return new FlexiMetaProperty(metaBean, propertyName); } /** * Constructor. * * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty */ private FlexiMetaProperty(MetaBean metaBean, String propertyName) { super(propertyName); this.metaBean = metaBean; } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return FlexiBean.class; } @Override public Class propertyType() { return Object.class; } @Override public Class propertyGenericType() { return Object.class; } @Override public PropertyStyle style() { return PropertyStyle.READ_WRITE; } @Override public List annotations() { return Collections.emptyList(); } //----------------------------------------------------------------------- @Override public Object get(Bean bean) { return ((FlexiBean) bean).propertyGet(name()); } @Override public void set(Bean bean, Object value) { ((FlexiBean) bean).propertySet(name(), value); } } ================================================ FILE: src/main/java/org/joda/beans/impl/flexi/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of Joda-Beans as a flexible map of data. *

* A {@code FlexiBean} is typically used as a dynamic bean where properties * can be added and removed at any time. This also makes it useful as an extension * to other beans, allowing a standard set of properties to be supplemented. */ package org.joda.beans.impl.flexi; ================================================ FILE: src/main/java/org/joda/beans/impl/light/LightBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.light; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; /** * Implementation of {@code BeanBuilder} that builds light beans. * * @param the bean type */ class LightBeanBuilder implements BeanBuilder { /** The meta-bean. */ private final LightMetaBean metaBean; /** The data. */ private final Object[] data; //----------------------------------------------------------------------- /** * Constructs the builder wrapping the target bean. * * @param metaBean the target meta-bean, not null * @param data the newly created data array */ LightBeanBuilder(LightMetaBean metaBean, Object[] data) { this.metaBean = metaBean; this.data = data; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { return get(metaBean.metaProperty(propertyName)); } @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { return (P) data[index(metaProperty)]; } //----------------------------------------------------------------------- @Override public BeanBuilder set(String propertyName, Object value) { return set(metaBean.metaProperty(propertyName), value); } @Override public BeanBuilder set(MetaProperty metaProperty, Object value) { data[index(metaProperty)] = value; return this; } private int index(MetaProperty metaProperty) { if (metaProperty instanceof LightMetaProperty mp) { var index = mp.getConstructorIndex(); if (index < 0) { throw new NoSuchElementException("Derived property cannot be set: " + metaProperty.name()); } return index; } return index(metaBean.metaProperty(metaProperty.name())); } //----------------------------------------------------------------------- @Override public B build() { return metaBean.build(data); } //----------------------------------------------------------------------- /** * Returns a string that summarises the builder. * * @return a summary string, not null */ @Override public String toString() { return "BeanBuilder for " + metaBean.beanName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/light/LightMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.light; import static java.util.stream.Collectors.joining; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Function; import java.util.stream.Stream; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; /** * A meta-bean implementation that operates using method handles. *

* The properties are found using the {@link PropertyDefinition} annotation. * There must be a constructor matching the property definitions (arguments of same order and types). *

* This uses method handles to avoid problems with reflection {@code setAccessible()} in Java SE 9. * * @param the type of the bean */ public final class LightMetaBean implements TypedMetaBean { /** * The empty object array. */ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; /** The bean type. */ private final Class beanType; /** The meta-property instances of the bean. */ private final Map> metaPropertyMap; /** The aliases. */ private final Map aliasMap; /** The constructor to use. */ private final Function constructorFn; /** The construction data array. */ private final Object[] constructionData; //----------------------------------------------------------------------- /** * Obtains an instance of the meta-bean using standard default values. *

* The properties will be determined using reflection to find the fields. * Each field must have a {@link PropertyDefinition} annotation. * The order of the properties is undefined as Java fields are not necessarily * returned in source code order. *

* The default values for primitives are determined automatically. * If the bean has non-primitive values like lists and maps that need defaulting * then {@link #of(Class, java.lang.invoke.MethodHandles.Lookup, String[], Object...)} * must be used. * * @param the type of the bean * @param beanType the bean type, not null * @param lookup the method handle lookup, not null * @return the meta-bean, not null */ public static LightMetaBean of(Class beanType, MethodHandles.Lookup lookup) { // the field name order is undefined // but since they are not being matched against default values that is OK return new LightMetaBean<>(beanType, lookup, fieldNames(beanType), EMPTY_OBJECT_ARRAY); } // determine the field names by reflection private static String[] fieldNames(Class beanType) { var fieldNames = new ArrayList(); for (var field : beanType.getDeclaredFields()) { if (!Modifier.isStatic(field.getModifiers()) && field.getAnnotation(PropertyDefinition.class) != null) { fieldNames.add(field.getName()); } } return fieldNames.toArray(new String[0]); } /** * Obtains an instance of the meta-bean specifying default values. *

* The properties will be determined using reflection to find the * {@link PropertyDefinition} annotation. *

* The field names must be specified as reflection does not return fields in source code order. * The default values must be provided if they cannot be determined automatically. * Default values for primitives are determined automatically, but empty lists and maps are not. * * @param the type of the bean * @param beanType the bean type, not null * @param lookup the method handle lookup, not null * @param fieldNames the field names, one for each property, not null * @param defaultValues the default values, one for each property, not null * @return the meta-bean, not null */ public static LightMetaBean of( Class beanType, MethodHandles.Lookup lookup, String[] fieldNames, Object... defaultValues) { return new LightMetaBean<>(beanType, lookup, fieldNames, defaultValues); } /** * Constructor. */ private LightMetaBean( Class beanType, MethodHandles.Lookup lookup, String[] fieldNames, Object[] defaultValues) { Objects.requireNonNull(beanType, "beanType must not be null"); Objects.requireNonNull(lookup, "lookup must not be null"); Objects.requireNonNull(fieldNames, "fieldNames must not be null"); Objects.requireNonNull(defaultValues, "defaultValues must not be null"); if (defaultValues.length > 0 && defaultValues.length != fieldNames.length) { throw new IllegalArgumentException("Number of default values must match number of fields"); } this.beanType = beanType; // handle ordered or random var map = new LinkedHashMap>(); var propertyTypes = new ArrayList>(); for (var fieldName : fieldNames) { Field field; try { field = beanType.getDeclaredField(fieldName); } catch (NoSuchFieldException ex) { throw new IllegalArgumentException(ex); } if (Modifier.isStatic(field.getModifiers())) { throw new IllegalArgumentException("Field must not be static"); } if (field.getAnnotation(PropertyDefinition.class) == null) { throw new IllegalArgumentException("Field must have PropertyDefinition annotation"); } var pdef = field.getAnnotation(PropertyDefinition.class); var name = field.getName(); if (pdef.get().isEmpty() || pdef.get().equals("field") || pdef.get().startsWith("optional")) { map.put(name, LightMetaProperty.of(this, field, lookup, name, propertyTypes.size())); } else { var getterName = "get" + name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1); Method getMethod = null; if (field.getType() == boolean.class) { getMethod = findGetMethod( beanType, "is" + name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1)); } if (getMethod == null) { getMethod = findGetMethod(beanType, getterName); if (getMethod == null) { throw new IllegalArgumentException( "Unable to find property getter: " + beanType.getSimpleName() + "." + getterName + "()"); } } Method setMethod = null; if (!ImmutableBean.class.isAssignableFrom(beanType)) { var setterName = "set" + name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1); setMethod = findSetMethod(beanType, setterName, field.getType()); if (setMethod == null) { throw new IllegalArgumentException( "Unable to find property setter: " + beanType.getSimpleName() + "." + setterName + "()"); } } map.put(name, LightMetaProperty.of(this, field, getMethod, setMethod, lookup, name, propertyTypes.size())); } propertyTypes.add(field.getType()); } var constructor = findConstructor(beanType, propertyTypes); var constructionData = defaultValues; if (defaultValues.length == 0) { constructionData = buildConstructionData(constructor); } // derived var methods = beanType.getDeclaredMethods(); for (var method : methods) { if (!Modifier.isStatic(method.getModifiers()) && method.getAnnotation(DerivedProperty.class) != null && method.getName().startsWith("get") && method.getName().length() > 3 && Character.isUpperCase(method.getName().charAt(3)) && method.getParameterTypes().length == 0) { var methodName = method.getName(); var propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); var mp = LightMetaProperty.of(this, method, lookup, propertyName, -1); map.put(propertyName, mp); } } this.metaPropertyMap = Collections.unmodifiableMap(map); this.aliasMap = new HashMap<>(); this.constructionData = constructionData; var handle = findConstructorHandle(beanType, lookup, constructor); this.constructorFn = args -> build(handle, args); } /** * Constructor used internally. */ private LightMetaBean( Class beanType, Map> metaPropertyMap, Map aliasMap, Function constructorFn, Object[] constructionData) { this.beanType = beanType; this.metaPropertyMap = metaPropertyMap; this.aliasMap = aliasMap; this.constructorFn = constructorFn; this.constructionData = constructionData; } // finds a method on class or public method on super-type private static Method findGetMethod(Class beanType, String getterName) { try { return beanType.getDeclaredMethod(getterName); } catch (NoSuchMethodException ex) { try { return beanType.getMethod(getterName); } catch (NoSuchMethodException ex2) { return null; } } } // finds a method on class or public method on super-type private static Method findSetMethod(Class beanType, String setterName, Class fieldType) { try { return beanType.getDeclaredMethod(setterName, fieldType); } catch (NoSuchMethodException ex) { var methods = beanType.getMethods(); var potential = new ArrayList(); for (var method : methods) { if (method.getName().equals(setterName) && method.getParameterTypes().length == 1) { potential.add(method); } } if (potential.size() == 1) { return potential.get(0); } for (Method method : potential) { if (method.getParameterTypes()[0].equals(fieldType)) { return method; } } return null; } } // finds constructor which matches types exactly private static MethodHandle findConstructorHandle( Class beanType, MethodHandles.Lookup lookup, Constructor constructor) { try { // spreader allows an Object[] to invoke the positional arguments var constructorType = MethodType.methodType(Void.TYPE, constructor.getParameterTypes()); var baseHandle = lookup.findConstructor(beanType, constructorType) .asSpreader(Object[].class, constructor.getParameterTypes().length); // change the return type so caller can use invokeExact() return baseHandle.asType(baseHandle.type().changeReturnType(Bean.class)); } catch (NoSuchMethodException ex) { throw new IllegalArgumentException("Unable to find constructor: " + beanType.getSimpleName()); } catch (IllegalAccessException ex) { throw new IllegalArgumentException("Unable to access constructor: " + beanType.getSimpleName()); } } // finds constructor which matches types exactly private static Constructor findConstructor(Class beanType, List> propertyTypes) { var types = propertyTypes.toArray(new Class[0]); try { return beanType.getDeclaredConstructor(types); } catch (NoSuchMethodException ex) { return findConstructorFallback(beanType, types, ex); } } // try a more lenient search // this handles cases where field is a concrete class and constructor is an interface private static Constructor findConstructorFallback(Class beanType, Class[] types, NoSuchMethodException ex) { @SuppressWarnings("unchecked") var cons = (Constructor[]) beanType.getDeclaredConstructors(); Constructor match = null; outer: for (var con : cons) { var conTypes = con.getParameterTypes(); if (conTypes.length == types.length) { for (var j = 0; j < types.length; j++) { if (!conTypes[j].isAssignableFrom(types[j])) { continue outer; } } if (match != null) { throw new UnsupportedOperationException("Unable to find constructor: More than one matches"); } match = con; } } if (match == null) { var signature = Stream.of(types).map(Class::getName).collect(joining(", ")); var msg = "Unable to find constructor: " + beanType.getSimpleName() + '(' + signature + ')'; throw new UnsupportedOperationException(msg, ex); } return match; } // array used to collect data when building // needs to have default values for primitives // note that this does not handle empty collections/maps private static Object[] buildConstructionData(Constructor constructor) { var parameterTypes = constructor.getParameterTypes(); var args = new Object[parameterTypes.length]; for (var i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i] == boolean.class) { args[i] = false; } else if (parameterTypes[i] == int.class) { args[i] = 0; } else if (parameterTypes[i] == long.class) { args[i] = (long) 0; } else if (parameterTypes[i] == short.class) { args[i] = (short) 0; } else if (parameterTypes[i] == byte.class) { args[i] = (byte) 0; } else if (parameterTypes[i] == float.class) { args[i] = (float) 0; } else if (parameterTypes[i] == double.class) { args[i] = (double) 0; } else if (parameterTypes[i] == char.class) { args[i] = (char) 0; } } return args; } @SuppressWarnings("unchecked") private T build(MethodHandle handle, Object[] args) { try { return (T) handle.invokeExact(args); } catch (Error ex) { throw ex; } catch (Throwable ex) { throw new IllegalArgumentException( "Bean cannot be created: " + beanName() + " from " + Arrays.toString(args), ex); } } //----------------------------------------------------------------------- T build(Object[] args) { return constructorFn.apply(args); } //----------------------------------------------------------------------- /** * Adds an alias to the meta-bean. *

* When using {@link #metaProperty(String)}, the alias will return the * meta-property of the real name. * * @param alias the alias * @param realName the real name * @return the new meta-bean instance * @throws IllegalArgumentException if the realName is invalid */ public LightMetaBean withAlias(String alias, String realName) { if (!metaPropertyMap.containsKey(realName)) { throw new IllegalArgumentException("Invalid property name: " + realName); } var aliasMap = new HashMap<>(this.aliasMap); aliasMap.put(alias, realName); return new LightMetaBean<>(beanType, metaPropertyMap, aliasMap, constructorFn, constructionData); } //----------------------------------------------------------------------- @Override public boolean isBuildable() { return true; } @Override public BeanBuilder builder() { return new LightBeanBuilder<>(this, constructionData.clone()); } @Override public Class beanType() { return beanType; } @Override @SuppressWarnings("unchecked") public MetaProperty metaProperty(String propertyName) { var mp = metaPropertyMap().get(aliasMap.getOrDefault(propertyName, propertyName)); if (mp == null) { throw new NoSuchElementException("Unknown property: " + propertyName); } return (MetaProperty) mp; } @Override public Map> metaPropertyMap() { return metaPropertyMap; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { return obj instanceof LightMetaBean other && this.beanType.equals(other.beanType); } @Override public int hashCode() { return beanType.hashCode() + 3; } /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/light/LightMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.light; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; import org.joda.beans.ResolvedType; import org.joda.beans.impl.BasicMetaProperty; /** * An immutable meta-property based on a getter interface. * * @param

the type of the property content */ final class LightMetaProperty

extends BasicMetaProperty

{ /** The meta-bean. */ private final MetaBean metaBean; /** The type of the property. */ private final Class

propertyType; /** The type of the property. */ private final Type propertyGenericType; /** The function to create the resolved type of the property. */ private final Function, ResolvedType> propertyResolvedTypeFn; /** The annotations. */ private final List annotations; /** The read method. */ private final MethodHandle getter; /** The optional write method. */ private final MethodHandle setter; /** The index of the property in the constructor. */ private final int constructorIndex; /** The property style. */ private final PropertyStyle style; //----------------------------------------------------------------------- /** * Creates an instance from a {@code Field}. * * @param

the property type * @param metaBean the meta bean, not null * @param field the field, not null * @param constructorIndex the index of the property in the constructor * @return the property, not null */ @SuppressWarnings("unchecked") static

LightMetaProperty

of( MetaBean metaBean, Field field, MethodHandles.Lookup lookup, String propertyName, int constructorIndex) { MethodHandle getter; try { getter = lookup.findGetter(field.getDeclaringClass(), field.getName(), field.getType()); } catch (IllegalArgumentException | NoSuchFieldException | IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be read: " + propertyName, ex); } MethodHandle setter = null; if (!Modifier.isFinal(field.getModifiers())) { try { setter = lookup.findSetter(field.getDeclaringClass(), field.getName(), field.getType()); } catch (IllegalArgumentException | NoSuchFieldException | IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be read: " + propertyName, ex); } } return new LightMetaProperty<>( metaBean, propertyName, (Class

) field.getType(), field.getGenericType(), Arrays.asList(field.getAnnotations()), getter, setter, constructorIndex, calculateStyle(metaBean, setter)); } /** * Creates an instance from a get/set {@code Method} pair. * * @param

the property type * @param metaBean the meta bean, not null * @param getMethod the method, not null * @param setMethod the method, not null * @param constructorIndex the index of the property in the constructor * @return the property, not null */ @SuppressWarnings("unchecked") static

LightMetaProperty

of( MetaBean metaBean, Field field, Method getMethod, Method setMethod, MethodHandles.Lookup lookup, String propertyName, int constructorIndex) { MethodHandle getter; try { var methodType = MethodType.methodType(getMethod.getReturnType(), getMethod.getParameterTypes()); getter = lookup.findVirtual(field.getDeclaringClass(), getMethod.getName(), methodType); } catch (IllegalArgumentException | NoSuchMethodException | IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be read: " + propertyName, ex); } MethodHandle setter = null; if (setMethod != null) { try { var methodType = MethodType.methodType(void.class, setMethod.getParameterTypes()); setter = lookup.findVirtual(field.getDeclaringClass(), setMethod.getName(), methodType); } catch (IllegalArgumentException | NoSuchMethodException | IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be written: " + propertyName, ex); } } return new LightMetaProperty<>( metaBean, propertyName, (Class

) field.getType(), field.getGenericType(), Arrays.asList(field.getAnnotations()), getter, setter, constructorIndex, calculateStyle(metaBean, setter)); } private static PropertyStyle calculateStyle(MetaBean metaBean, MethodHandle setter) { if (ImmutableBean.class.isAssignableFrom(metaBean.beanType())) { return PropertyStyle.IMMUTABLE; } return setter != null ? PropertyStyle.READ_WRITE : PropertyStyle.READ_ONLY; } /** * Creates an instance from a derived {@code Method}. * * @param

the property type * @param metaBean the meta bean, not null * @param getMethod the get method, not null * @param constructorIndex the index of the property * @return the property, not null */ @SuppressWarnings("unchecked") static

LightMetaProperty

of( MetaBean metaBean, final Method getMethod, MethodHandles.Lookup lookup, final String propertyName, int constructorIndex) { MethodHandle getter; try { getter = lookup.unreflect(getMethod); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be read: " + propertyName, ex); } return new LightMetaProperty<>( metaBean, propertyName, (Class

) getMethod.getReturnType(), getMethod.getGenericReturnType(), Arrays.asList(getMethod.getAnnotations()), getter, null, constructorIndex, PropertyStyle.DERIVED); } /** * Creates an instance. * * @param metaBean the meta bean, not null * @param propertyName the property name, not empty * @param propertyType the property type * @param propertyGenericType the property generic type * @param annotations the annotations * @param getter the property getter * @param setter the property setter * @param constructorIndex the index of the property in the constructor */ LightMetaProperty( MetaBean metaBean, String propertyName, Class

propertyType, Type propertyGenericType, List annotations, MethodHandle getter, MethodHandle setter, int constructorIndex, PropertyStyle style) { super(propertyName); this.metaBean = metaBean; this.propertyType = propertyType; this.propertyGenericType = propertyGenericType; this.annotations = annotations; this.getter = getter.asType(MethodType.methodType(Object.class, Bean.class)); this.setter = setter != null ? setter.asType(MethodType.methodType(void.class, Bean.class, Object.class)) : null; this.constructorIndex = constructorIndex; this.style = style; var beanType = metaBean.beanType(); var resolvedType = ResolvedType.from(propertyGenericType, beanType); this.propertyResolvedTypeFn = !resolvedType.isParameterized() || Modifier.isFinal(beanType.getModifiers()) ? contextClass -> resolvedType : contextClass -> contextClass == beanType ? resolvedType : ResolvedType.from(propertyGenericType, contextClass); } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return metaBean.beanType(); } @Override public Class

propertyType() { return propertyType; } @Override public Type propertyGenericType() { return propertyGenericType; } @Override public ResolvedType propertyResolvedType(Class contextClass) { return propertyResolvedTypeFn.apply(contextClass); } @Override public PropertyStyle style() { return style; } @Override public List annotations() { return annotations; } //----------------------------------------------------------------------- @Override public P get(Bean bean) { try { return (P) getter.invokeExact(bean); } catch (RuntimeException | Error ex) { throw ex; } catch (Throwable ex) { throw new RuntimeException(ex); } } @Override public void set(Bean bean, Object value) { if (setter == null) { throw new UnsupportedOperationException("Property cannot be written: " + name()); } try { setter.invokeExact(bean, value); } catch (RuntimeException | Error ex) { throw ex; } catch (Throwable ex) { throw new RuntimeException(ex); } } int getConstructorIndex() { return constructorIndex; } } ================================================ FILE: src/main/java/org/joda/beans/impl/light/PropertyGetter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.light; import org.joda.beans.Bean; /** * Functional interface providing the ability to get a property from a bean. */ interface PropertyGetter { /** * Queries the property. * * @param bean the bean to query * @return the property value */ Object get(Bean bean); } ================================================ FILE: src/main/java/org/joda/beans/impl/light/PropertySetter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.light; import org.joda.beans.Bean; /** * Functional interface providing the ability to set a property in a bean. */ interface PropertySetter { /** * Sets the property. * * @param bean the bean to change * @param value the value to set */ void set(Bean bean, Object value); } ================================================ FILE: src/main/java/org/joda/beans/impl/light/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of light immutable Joda-Beans. */ package org.joda.beans.impl.light; ================================================ FILE: src/main/java/org/joda/beans/impl/map/MapBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.map; import java.io.Serial; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.joda.beans.DynamicBean; import org.joda.beans.DynamicMetaBean; import org.joda.beans.Property; import org.joda.beans.impl.BasicProperty; import org.joda.beans.impl.flexi.FlexiBean; /** * Implementation of a fully dynamic {@code Bean} based on an exposed {@code Map}. *

* Properties are dynamic, and can be added and removed at will from the map. *

* This class extends {@link HashMap}, allowing it to be used wherever a map is. * See {@link FlexiBean} for a map-like bean implementation that is more controlled. */ public class MapBean extends HashMap implements DynamicBean { /** Serialization version. */ @Serial private static final long serialVersionUID = 1L; //----------------------------------------------------------------------- /** * Creates a standalone meta-bean. *

* This creates a new instance each time in line with dynamic bean principles. * * @return the meta-bean, not null */ public static DynamicMetaBean meta() { return new MapBean().metaBean(); } //----------------------------------------------------------------------- /** * Creates an instance. */ public MapBean() { } /** * Creates an instance. * * @param map the map to copy, not null */ private MapBean(Map map) { super(map); } //----------------------------------------------------------------------- @Override public DynamicMetaBean metaBean() { return new MapMetaBean(this); } @Override public Property property(String name) { return BasicProperty.of(this, MapBeanMetaProperty.of(metaBean(), name)); } @Override public Set propertyNames() { return keySet(); } @Override public void propertyDefine(String propertyName, Class propertyType) { if (!containsKey(propertyName)) { put(propertyName, null); } } @Override public void propertyRemove(String propertyName) { remove(propertyName); } @Override public MapBean clone() { return new MapBean(this); } //----------------------------------------------------------------------- /** * Returns a string that summarises the bean. *

* The string contains the class name and properties. * * @return a summary string, not null */ @Override public String toString() { return getClass().getSimpleName() + super.toString(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/map/MapBeanBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.map; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; /** * Implementation of a meta-bean for {@code MapBean}. */ class MapBeanBuilder implements BeanBuilder { /** * The bean itself. */ private final MapBean bean; /** * Creates the meta-bean. * * @param bean the underlying bean, not null */ MapBeanBuilder(MapBean bean) { this.bean = bean; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { // lenient getter return bean.get(propertyName); } @Override @SuppressWarnings("unchecked") public

P get(MetaProperty

metaProperty) { // this approach allows meta-property from one bean to be used with another return (P) bean.get(metaProperty.name()); } //----------------------------------------------------------------------- @Override public MapBeanBuilder set(String propertyName, Object value) { bean.put(propertyName, value); return this; } @Override public MapBeanBuilder set(MetaProperty metaProperty, Object value) { // this approach allows meta-property from one bean to be used with another bean.put(metaProperty.name(), value); return this; } @Override public MapBean build() { return bean; } //----------------------------------------------------------------------- @Override public String toString() { return "MapBeanBuilder"; } } ================================================ FILE: src/main/java/org/joda/beans/impl/map/MapBeanMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.map; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.List; import org.joda.beans.Bean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; import org.joda.beans.impl.BasicMetaProperty; /** * A meta-property using a {@code MapBean} for storage. */ final class MapBeanMetaProperty extends BasicMetaProperty { /** The meta-bean. */ private final MetaBean metaBean; /** * Factory to create a meta-property. * * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty */ static MapBeanMetaProperty of(MetaBean metaBean, String propertyName) { return new MapBeanMetaProperty(metaBean, propertyName); } /** * Constructor. * * @param metaBean the meta-bean, not null * @param propertyName the property name, not empty */ private MapBeanMetaProperty(MetaBean metaBean, String propertyName) { super(propertyName); this.metaBean = metaBean; } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return MapBean.class; } @Override public Class propertyType() { return Object.class; } @Override public Class propertyGenericType() { return Object.class; } @Override public PropertyStyle style() { return PropertyStyle.READ_WRITE; } @Override public List annotations() { return Collections.emptyList(); } //----------------------------------------------------------------------- @Override public Object get(Bean bean) { return ((MapBean) bean).get(name()); } @Override public void set(Bean bean, Object value) { ((MapBean) bean).put(name(), value); } } ================================================ FILE: src/main/java/org/joda/beans/impl/map/MapMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.map; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.DynamicMetaBean; import org.joda.beans.MetaProperty; /** * Implementation of a meta-bean for {@code MapBean}. */ class MapMetaBean implements DynamicMetaBean { /** * The bean itself. */ private final MapBean bean; /** * Creates the meta-bean. * * @param bean the underlying bean, not null */ MapMetaBean(MapBean bean) { this.bean = bean; } //----------------------------------------------------------------------- @Override public boolean isBuildable() { return true; } @Override public BeanBuilder builder() { return new MapBeanBuilder(bean); } @Override public Class beanType() { return MapBean.class; } @Override public int metaPropertyCount() { return bean.size(); } @Override public boolean metaPropertyExists(String name) { return bean.containsKey(name); } @Override public MetaProperty metaProperty(String name) { // do not check if exists return MapBeanMetaProperty.of(this, name); } @Override public Iterable> metaPropertyIterable() { return () -> { var it = bean.keySet().iterator(); return new Iterator<>() { @Override public boolean hasNext() { return it.hasNext(); } @Override public MetaProperty next() { return MapBeanMetaProperty.of(MapMetaBean.this, it.next()); } @Override public void remove() { throw new UnsupportedOperationException("Unmodifiable"); } }; }; } @Override public Map> metaPropertyMap() { var keySet = bean.keySet(); var map = LinkedHashMap.>newLinkedHashMap(keySet.size()); for (var name : bean.keySet()) { map.put(name, MapBeanMetaProperty.of(this, name)); } return Collections.unmodifiableMap(map); } //----------------------------------------------------------------------- @Override public void metaPropertyDefine(String propertyName, Class propertyType) { bean.propertyDefine(propertyName, propertyType); } @Override public void metaPropertyRemove(String propertyName) { bean.propertyRemove(propertyName); } @Override public List annotations() { return Collections.emptyList(); } /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanType().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/map/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of Joda-Beans extending a map. *

* A {@code MapBean} is a dynamic bean that extends a {@code HashMap}. * This is similar to a {@code FlexiBean}, but used if you need a map implementatino. */ package org.joda.beans.impl.map; ================================================ FILE: src/main/java/org/joda/beans/impl/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Base implementations of Joda-Bean interfaces. *

* The Joda-Bean interfaces introduce a number of concepts and this package introduces * basic implementations of them. The implementations are in a simple and standard form. * It is recommended to extend these base classes where possible, however there may * be a faster implementation available. */ package org.joda.beans.impl; ================================================ FILE: src/main/java/org/joda/beans/impl/reflection/ReflectiveMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.reflection; import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.impl.BasicBeanBuilder; /** * A meta-bean implementation that uses reflection. *

* This is implementation of a meta-bean can be used directly by applications without code generation. * It requires that the bean implements {@code Bean} and has a no-arguments constructor. * Therefore, it is only suitable for mutable beans. *

* Typically, the meta-bean will be created as a public static final constant. * Only one method from {@link Bean} needs to be implemented, which simply returns the meta-bean. * * @param the type of the bean */ public final class ReflectiveMetaBean implements TypedMetaBean { /** The bean type. */ private final Class beanType; /** The meta-property instances of the bean. */ private final Map> metaPropertyMap; /** * Create a meta-bean and meta properties. *

* The meta-properties will be created from the property names by searching for a getter and setter. * * @param the type of the bean * @param beanClass the bean class, not null * @param propertyNames the property names, not null * @return the meta-bean, not null */ public static ReflectiveMetaBean of(Class beanClass, String... propertyNames) { return new ReflectiveMetaBean<>(beanClass, propertyNames); } /** * Constructor. * * @param beanType the bean type, not null * @param propertyNames the property names, not null */ private ReflectiveMetaBean(Class beanType, String[] propertyNames) { Objects.requireNonNull(beanType, "beanType must not be null"); Objects.requireNonNull(propertyNames, "propertyNames must not be null"); this.beanType = beanType; var map = new LinkedHashMap>(); for (var name : propertyNames) { map.put(name, new ReflectiveMetaProperty<>(this, beanType, name)); } this.metaPropertyMap = Collections.unmodifiableMap(map); } //----------------------------------------------------------------------- @Override public boolean isBuildable() { try { beanType.getDeclaredConstructor().newInstance(); return true; } catch (Exception ex) { return false; } } @Override public BeanBuilder builder() { try { var bean = beanType.getDeclaredConstructor().newInstance(); return new BasicBeanBuilder<>(bean); } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) { throw new UnsupportedOperationException("Bean cannot be created: " + beanName(), ex); } } @Override public Class beanType() { return beanType; } @Override public Map> metaPropertyMap() { return metaPropertyMap; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { return obj instanceof ReflectiveMetaBean other && this.beanType.equals(other.beanType); } @Override public int hashCode() { return beanType.hashCode() + 3; } /** * Returns a string that summarises the meta-bean. * * @return a summary string, not null */ @Override public String toString() { return "MetaBean:" + beanName(); } } ================================================ FILE: src/main/java/org/joda/beans/impl/reflection/ReflectiveMetaProperty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.impl.reflection; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.PropertyStyle; import org.joda.beans.impl.BasicMetaProperty; /** * A meta-property implemented using a {@code PropertyDescriptor}. *

* The property descriptor class is part of the JDK JavaBean standard. * It provides access to get and set a property on a bean. *

* Instances of this class should be declared as a static constant on the bean, * one for each property, followed by a {@code ReflectiveMetaBean} declaration. * * @param

the type of the property content */ final class ReflectiveMetaProperty

extends BasicMetaProperty

{ /** The meta-bean. */ private volatile MetaBean metaBean; /** The declaring type. */ private final Class declaringType; /** The type of the property. */ private final Class

propertyType; /** The getter. */ private final Method getMethod; /** The setter. */ private final Method setMethod; /** * Constructor using {@code PropertyDescriptor} to find the get and set methods. * * @param metaBean the meta-bean * @param beanType the bean type, not null * @param propertyName the property name, not empty */ @SuppressWarnings({"unchecked", "null"}) ReflectiveMetaProperty(MetaBean metaBean, Class beanType, String propertyName) { super(propertyName); var getterName = "get" + propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1); var isserName = "is" + propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1); var getMethod = findGetMethod(beanType, getterName); var isMethod = findGetMethod(beanType, isserName); if (getMethod == null && isMethod == null) { throw new IllegalArgumentException( "Unable to find property getter: " + beanType.getSimpleName() + "." + getterName + "()"); } getMethod = isMethod != null ? isMethod : getMethod; Method setMethod = null; if (!ImmutableBean.class.isAssignableFrom(beanType)) { var setterName = "set" + propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1); setMethod = findSetMethod(beanType, setterName, getMethod.getReturnType()); if (setMethod == null) { throw new IllegalArgumentException( "Unable to find property setter: " + beanType.getSimpleName() + "." + setterName + "()"); } } this.metaBean = metaBean; this.declaringType = (getMethod != null ? getMethod.getDeclaringClass() : setMethod.getDeclaringClass()); this.propertyType = (Class

) getMethod.getReturnType(); this.getMethod = getMethod; this.setMethod = setMethod; } // finds a method on class or public method on super-type private static Method findGetMethod(Class beanType, String getterName) { try { return beanType.getDeclaredMethod(getterName); } catch (NoSuchMethodException ex) { try { return beanType.getMethod(getterName); } catch (NoSuchMethodException ex2) { return null; } } } // finds a method on class or public method on super-type private static Method findSetMethod(Class beanType, String setterName, Class fieldType) { try { return beanType.getDeclaredMethod(setterName, fieldType); } catch (NoSuchMethodException ex) { var methods = beanType.getMethods(); var potential = new ArrayList(); for (var method : methods) { if (method.getName().equals(setterName) && method.getParameterTypes().length == 1) { potential.add(method); } } if (potential.size() == 1) { return potential.get(0); } for (var method : potential) { if (method.getParameterTypes()[0].equals(fieldType)) { return method; } } return null; } } /** * Sets the meta-bean, necessary due to ordering restrictions during loading. * @param metaBean the meta-bean, not null */ void setMetaBean(MetaBean metaBean) { this.metaBean = metaBean; } //----------------------------------------------------------------------- @Override public MetaBean metaBean() { return metaBean; } @Override public Class declaringType() { return declaringType; } @Override public Class

propertyType() { return propertyType; } @Override public Type propertyGenericType() { if (getMethod != null) { return getMethod.getGenericReturnType(); } return setMethod.getGenericParameterTypes()[0]; } @Override public PropertyStyle style() { return (getMethod == null ? PropertyStyle.WRITE_ONLY : (setMethod == null ? PropertyStyle.READ_ONLY : PropertyStyle.READ_WRITE)); } @Override public List annotations() { if (getMethod != null) { return Arrays.asList(getMethod.getDeclaredAnnotations()); } return Arrays.asList(setMethod.getDeclaredAnnotations()); } //----------------------------------------------------------------------- @Override @SuppressWarnings("unchecked") public P get(Bean bean) { if (!style().isReadable()) { throw new UnsupportedOperationException("Property cannot be read: " + name()); } try { return (P) getMethod.invoke(bean, (Object[]) null); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be read: " + name(), ex); } catch (InvocationTargetException ex) { if (ex.getCause() instanceof RuntimeException) { throw (RuntimeException) ex.getCause(); } throw new RuntimeException(ex); } } @SuppressWarnings("null") @Override public void set(Bean bean, Object value) { if (!style().isWritable()) { throw new UnsupportedOperationException("Property cannot be written: " + name()); } try { setMethod.invoke(bean, value); } catch (IllegalArgumentException ex) { if (value == null && setMethod.getParameterTypes()[0].isPrimitive()) { throw new NullPointerException("Property cannot be written: " + name() + ": Cannot store null in primitive"); } if (!propertyType.isInstance(value)) { throw new ClassCastException("Property cannot be written: " + name() + ": Invalid type: " + value.getClass().getName()); } throw new UnsupportedOperationException("Property cannot be written: " + name(), ex); } catch (IllegalAccessException ex) { throw new UnsupportedOperationException("Property cannot be written: " + name(), ex); } catch (InvocationTargetException ex) { if (ex.getCause() instanceof RuntimeException) { throw (RuntimeException) ex.getCause(); } throw new RuntimeException(ex); } } } ================================================ FILE: src/main/java/org/joda/beans/impl/reflection/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of Joda-Beans using reflection. *

* This package implements a Joda-Bean via reflection. */ package org.joda.beans.impl.reflection; ================================================ FILE: src/main/java/org/joda/beans/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Base interfaces and annotations defining Joda-Beans. *

* Joda-Beans is a library that can be used to provide enhanced Java Beans. * These extensions provide the tools for framework writers to access bean and property * information in a consistent and fast manner, typically without reflection. *

* A Joda-Bean implements the {@code Bean} interface. In turn, this requires the * creation of a {@code MetaBean} implementation, typically an inner class. * Both also require the provision of implementations of {@code Property} and * {@code MetaProperty} to express the properties of the bean. *

* Other packages provide implementations of the interfaces and a code generator. */ package org.joda.beans; ================================================ FILE: src/main/java/org/joda/beans/ser/CollectSerIteratorFactory.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableCell; import org.joda.collect.grid.ImmutableGrid; /** * Factory used to create wrappers around collection-like objects. */ public class CollectSerIteratorFactory extends GuavaSerIteratorFactory { /** * Creates an iterator wrapper for a meta-property value. * * @param value the possible collection-like object, not null * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @return the iterator, null if not a collection-like type */ @Override public SerIterator create(Object value, MetaProperty prop, Class beanClass) { var declaredType = prop.propertyType(); if (value instanceof Grid grid) { var valueType = defaultToObjectClass(JodaBeanUtils.collectionType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return grid(grid, declaredType, valueType, valueTypeTypes); } return super.create(value, prop, beanClass); } /** * Creates an iterator wrapper for a value retrieved from a parent iterator. *

* Allows the parent iterator to define the child iterator using generic type information. * This handles cases such as a {@code List} as the value in a {@code Map}. * * @param value the possible collection-like object, not null * @param parent the parent iterator, not null * @return the iterator, null if not a collection-like type */ @Override public SerIterator createChild(Object value, SerIterator parent) { var declaredType = parent.valueType(); var childGenericTypes = parent.valueTypeTypes(); if (value instanceof Grid grid) { if (childGenericTypes.size() == 1) { return grid(grid, declaredType, childGenericTypes.get(0), EMPTY_VALUE_TYPES); } return grid(grid, Object.class, Object.class, EMPTY_VALUE_TYPES); } return super.createChild(value, parent); } //----------------------------------------------------------------------- /** * Creates an iterator wrapper for a meta-property value. * * @param metaTypeDescription the description of the collection type, not null * @param settings the settings object, not null * @param knownTypes the known types map, null if not using known type shortening * @return the iterator, null if not a collection-like type */ @Override public SerIterable createIterable(String metaTypeDescription, JodaBeanSer settings, Map> knownTypes) { if (metaTypeDescription.equals("Grid")) { return grid(Object.class, EMPTY_VALUE_TYPES); } return super.createIterable(metaTypeDescription, settings, knownTypes); } /** * Creates an iterator wrapper for a meta-property value. * * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @return the iterator, null if not a collection-like type */ @Override public SerIterable createIterable(MetaProperty prop, Class beanClass) { if (Grid.class.isAssignableFrom(prop.propertyType())) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return grid(valueType, valueTypeTypes); } return super.createIterable(prop, beanClass); } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for {@code Grid}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable grid(Class valueType, List> valueTypeTypes) { return new SerIterable() { private final List> cells = new ArrayList<>(); private int[] dimensions; @Override public SerIterator iterator() { return grid(build(), Object.class, valueType, valueTypeTypes); } @Override public void dimensions(int[] dimensions) { this.dimensions = dimensions; } @Override public void add(Object key, Object column, Object value, int count) { if (value != null) { cells.add(ImmutableCell.of((Integer) key, (Integer) column, value)); } } @Override @SuppressWarnings({"unchecked", "rawtypes"}) public Grid build() { if (dimensions == null || dimensions.length != 2) { throw new IllegalArgumentException("Expected 2 dimensions, rowCount and columnCount"); } return ImmutableGrid.copyOf(dimensions[0], dimensions[1], (Iterable) cells); } @Override public SerCategory category() { return SerCategory.GRID; } @Override public Class keyType() { return Integer.class; } @Override public Class columnType() { return Integer.class; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterator wrapper for {@code Grid}. * * @param grid the collection, not null * @param declaredType the declared type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator grid(Grid grid, Class declaredType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = grid.cells().iterator(); private Grid.Cell current; @Override public String metaTypeName() { return "Grid"; } @Override public boolean metaTypeRequired() { return !Grid.class.isAssignableFrom(declaredType); } @Override public SerCategory category() { return SerCategory.GRID; } @Override public int dimensionSize(int dimension) { return (dimension == 0 ? grid.rowCount() : grid.columnCount()); } @Override public int size() { return grid.size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = (Grid.Cell) it.next(); } @Override public Class keyType() { return Integer.class; } @Override public Object key() { return current.getRow(); } @Override public Class columnType() { return Integer.class; } @Override public Object column() { return current.getColumn(); } @Override public Class valueType() { return valueType; } @Override public Object value() { return current.getValue(); } @Override public Object value(int row, int column) { return grid.get(row, column); } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } } ================================================ FILE: src/main/java/org/joda/beans/ser/DefaultDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; /** * Default deserializer that expects the input to match the current classpath beans. *

* This uses the standard {@code MetaBean}, {@code MetaProperty} and {@code BeanBuilder}. */ public class DefaultDeserializer implements SerDeserializer { /** * Singleton. */ public static final SerDeserializer INSTANCE = new DefaultDeserializer(); /** * Creates an instance. */ protected DefaultDeserializer() { } //----------------------------------------------------------------------- @Override public MetaBean findMetaBean(Class beanType) { return MetaBean.of(beanType); } @Override public BeanBuilder createBuilder(Class beanType, MetaBean metaBean) { return metaBean.builder(); } @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { return metaBean.metaProperty(propertyName); } @Override public void setValue(BeanBuilder builder, MetaProperty metaProp, Object value) { builder.set(metaProp, value); } @Override public Object build(Class beanType, BeanBuilder builder) { return builder.build(); } //----------------------------------------------------------------------- @Override public String toString() { return getClass().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/ser/GuavaSerIteratorFactory.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.BiMap; import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashBiMap; import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.Ordering; import com.google.common.collect.SetMultimap; import com.google.common.collect.SortedMultiset; import com.google.common.collect.Table; import com.google.common.collect.Table.Cell; import com.google.common.collect.TreeMultiset; /** * Guava factory used to create wrappers around collection-like objects. */ public class GuavaSerIteratorFactory extends SerIteratorFactory { /** * Creates an iterator wrapper for a meta-property value. * * @param value the possible collection-like object, not null * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @return the iterator, null if not a collection-like type */ @Override public SerIterator create(Object value, MetaProperty prop, Class beanClass) { var declaredType = prop.propertyType(); switch (value) { case BiMap map -> { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return biMap(map, declaredType, keyType, valueType, valueTypeTypes); } case Multiset multiset -> { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return multiset(multiset, declaredType, valueType, valueTypeTypes); } case Multimap multimap -> { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return multimap(multimap, declaredType, keyType, valueType, valueTypeTypes); } case Table table -> { var rowType = JodaBeanUtils.extractTypeClass(prop, beanClass, 3, 0); var colType = JodaBeanUtils.extractTypeClass(prop, beanClass, 3, 1); var valueType = JodaBeanUtils.extractTypeClass(prop, beanClass, 3, 2); return table(table, declaredType, rowType, colType, valueType, EMPTY_VALUE_TYPES); } case null, default -> { return super.create(value, prop, beanClass); } } } /** * Creates an iterator wrapper for a value retrieved from a parent iterator. *

* Allows the parent iterator to define the child iterator using generic type information. * This handles cases such as a {@code List} as the value in a {@code Map}. * * @param value the possible collection-like object, not null * @param parent the parent iterator, not null * @return the iterator, null if not a collection-like type */ @Override public SerIterator createChild(Object value, SerIterator parent) { var declaredType = parent.valueType(); var childGenTypes = parent.valueTypeTypes(); switch (value) { case BiMap map -> { if (childGenTypes.size() == 2) { return biMap(map, declaredType, childGenTypes.get(0), childGenTypes.get(1), EMPTY_VALUE_TYPES); } return biMap(map, Object.class, Object.class, Object.class, EMPTY_VALUE_TYPES); } case Multimap multimap -> { if (childGenTypes.size() == 2) { return multimap(multimap, declaredType, childGenTypes.get(0), childGenTypes.get(1), EMPTY_VALUE_TYPES); } return multimap(multimap, Object.class, Object.class, Object.class, EMPTY_VALUE_TYPES); } case Multiset multiset -> { if (childGenTypes.size() == 1) { return multiset(multiset, declaredType, childGenTypes.get(0), EMPTY_VALUE_TYPES); } return multiset(multiset, Object.class, Object.class, EMPTY_VALUE_TYPES); } case Table table -> { if (childGenTypes.size() == 3) { return table(table, declaredType, childGenTypes.get(0), childGenTypes.get(1), childGenTypes.get(2), EMPTY_VALUE_TYPES); } return table(table, Object.class, Object.class, Object.class, Object.class, EMPTY_VALUE_TYPES); } case null, default -> { return super.createChild(value, parent); } } } //----------------------------------------------------------------------- /** * Creates an iterator wrapper for a meta-property value. * * @param metaTypeDescription the description of the collection type, not null * @param settings the settings object, not null * @param knownTypes the known types map, null if not using known type shortening * @return the iterator, null if not a collection-like type */ @Override public SerIterable createIterable(String metaTypeDescription, JodaBeanSer settings, Map> knownTypes) { return switch (metaTypeDescription) { case "BiMap" -> biMap(Object.class, Object.class, EMPTY_VALUE_TYPES); case "SetMultimap" -> setMultimap(Object.class, Object.class, EMPTY_VALUE_TYPES); case "ListMultimap", "Multimap" -> listMultimap(Object.class, Object.class, EMPTY_VALUE_TYPES); case "Multiset" -> multiset(Object.class, EMPTY_VALUE_TYPES); case "Table" -> table(Object.class, Object.class, Object.class, EMPTY_VALUE_TYPES); default -> super.createIterable(metaTypeDescription, settings, knownTypes); }; } /** * Creates an iterator wrapper for a meta-property value. * * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @return the iterator, null if not a collection-like type */ @Override public SerIterable createIterable(MetaProperty prop, Class beanClass) { if (BiMap.class.isAssignableFrom(prop.propertyType())) { var keyType = defaultToObjectClass(JodaBeanUtils.mapKeyType(prop, beanClass)); var valueType = defaultToObjectClass(JodaBeanUtils.mapValueType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return biMap(keyType, valueType, valueTypeTypes); } if (SortedMultiset.class.isAssignableFrom(prop.propertyType())) { var valueType = defaultToObjectClass(JodaBeanUtils.collectionType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return sortedMultiset(valueType, valueTypeTypes); } if (Multiset.class.isAssignableFrom(prop.propertyType())) { var valueType = defaultToObjectClass(JodaBeanUtils.collectionType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return multiset(valueType, valueTypeTypes); } if (SetMultimap.class.isAssignableFrom(prop.propertyType())) { var keyType = defaultToObjectClass(JodaBeanUtils.mapKeyType(prop, beanClass)); var valueType = defaultToObjectClass(JodaBeanUtils.mapValueType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return setMultimap(keyType, valueType, valueTypeTypes); } if (ListMultimap.class.isAssignableFrom(prop.propertyType()) || Multimap.class.isAssignableFrom(prop.propertyType())) { var keyType = defaultToObjectClass(JodaBeanUtils.mapKeyType(prop, beanClass)); var valueType = defaultToObjectClass(JodaBeanUtils.mapValueType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return listMultimap(keyType, valueType, valueTypeTypes); } if (Table.class.isAssignableFrom(prop.propertyType())) { var rowType = defaultToObjectClass(JodaBeanUtils.extractTypeClass(prop, beanClass, 3, 0)); var colType = defaultToObjectClass(JodaBeanUtils.extractTypeClass(prop, beanClass, 3, 1)); var valueType = defaultToObjectClass(JodaBeanUtils.extractTypeClass(prop, beanClass, 3, 2)); return table(rowType, colType, valueType, EMPTY_VALUE_TYPES); } if (ImmutableList.class.isAssignableFrom(prop.propertyType())) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return immutableList(valueType, valueTypeTypes); } if (ImmutableSortedSet.class.isAssignableFrom(prop.propertyType())) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return immutableSortedSet(valueType, valueTypeTypes); } if (ImmutableSet.class.isAssignableFrom(prop.propertyType())) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return immutableSet(valueType, valueTypeTypes); } if (ImmutableSortedMap.class.isAssignableFrom(prop.propertyType())) { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return immutableSortedMap(keyType, valueType, valueTypeTypes); } if (ImmutableMap.class.isAssignableFrom(prop.propertyType())) { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return immutableMap(keyType, valueType, valueTypeTypes); } return super.createIterable(prop, beanClass); } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for {@code BiMap}. * * @param keyType the value type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable biMap(Class keyType, Class valueType, List> valueTypeTypes) { BiMap map = HashBiMap.create(); return map(keyType, valueType, valueTypeTypes, map); } /** * Gets an iterable wrapper for {@code Multiset}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable multiset(Class valueType, List> valueTypeTypes) { Multiset coll = HashMultiset.create(); return multiset(valueType, valueTypeTypes, coll); } /** * Gets an iterable wrapper for {@code SortedMultiset}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ @SuppressWarnings({"rawtypes", "unchecked"}) public static SerIterable sortedMultiset(Class valueType, List> valueTypeTypes) { Ordering natural = Ordering.natural(); SortedMultiset coll = TreeMultiset.create(natural); return multiset(valueType, valueTypeTypes, coll); } private static SerIterable multiset(Class valueType, List> valueTypeTypes, Multiset coll) { return new SerIterable() { @Override public SerIterator iterator() { return multiset(coll, Object.class, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } coll.add(value, count); } @Override public Object build() { return coll; } @Override public SerCategory category() { return SerCategory.COUNTED; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterator wrapper for {@code Multiset}. * * @param multiset the collection, not null * @param declaredType the declared type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator multiset( Multiset multiset, Class declaredType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = multiset.entrySet().iterator(); private Multiset.Entry current; @Override public String metaTypeName() { return "Multiset"; } @Override public boolean metaTypeRequired() { return !Multiset.class.isAssignableFrom(declaredType); } @Override public SerCategory category() { return SerCategory.COUNTED; } @Override public int size() { return multiset.entrySet().size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = (Multiset.Entry) it.next(); } @Override public int count() { return current.getCount(); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } @Override public Object value() { return current.getElement(); } }; } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for {@code ListMultimap}. * * @param keyType the key type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable listMultimap(Class keyType, Class valueType, List> valueTypeTypes) { ListMultimap map = ArrayListMultimap.create(); return new SerIterable() { @Override public SerIterator iterator() { return multimap(map, Object.class, keyType, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key == null) { throw new IllegalArgumentException("Missing key"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } map.put(key, value); } @Override public Object build() { return map; } @Override public SerCategory category() { return SerCategory.MAP; } @Override public Class keyType() { return keyType; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterable wrapper for {@code SetMultimap}. * * @param keyType the key type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable setMultimap(Class keyType, Class valueType, List> valueTypeTypes) { SetMultimap map = HashMultimap.create(); return new SerIterable() { @Override public SerIterator iterator() { return multimap(map, Object.class, keyType, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key == null) { throw new IllegalArgumentException("Missing key"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } map.put(key, value); } @Override public Object build() { return map; } @Override public SerCategory category() { return SerCategory.MAP; } @Override public Class keyType() { return keyType; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterator wrapper for {@code Multimap}. * * @param map the collection, not null * @param declaredType the declared type, not null * @param keyType the key type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator multimap( Multimap map, Class declaredType, Class keyType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = map.entries().iterator(); private Map.Entry current; @Override public String metaTypeName() { if (map instanceof SetMultimap) { return "SetMultimap"; } if (map instanceof ListMultimap) { return "ListMultimap"; } return "Multimap"; } @Override public boolean metaTypeRequired() { if (map instanceof SetMultimap) { return !SetMultimap.class.isAssignableFrom(declaredType); } if (map instanceof ListMultimap) { return !ListMultimap.class.isAssignableFrom(declaredType); } return !Multimap.class.isAssignableFrom(declaredType); } @Override public SerCategory category() { return SerCategory.MAP; } @Override public int size() { return map.size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = (Map.Entry) it.next(); } @Override public Class keyType() { return keyType; } @Override public Object key() { return current.getKey(); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } @Override public Object value() { return current.getValue(); } }; } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for {@code Table}. * * @param rowType the row type, not null * @param colType the column type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable table(Class rowType, Class colType, Class valueType, List> valueTypeTypes) { Table table = HashBasedTable.create(); return new SerIterable() { @Override public SerIterator iterator() { return table(table, Object.class, rowType, colType, valueType, valueTypeTypes); } @Override public void add(Object row, Object column, Object value, int count) { if (row == null) { throw new IllegalArgumentException("Missing row"); } if (column == null) { throw new IllegalArgumentException("Missing column"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } table.put(row, column, value); } @Override public Object build() { return table; } @Override public SerCategory category() { return SerCategory.TABLE; } @Override public Class keyType() { return rowType; } @Override public Class columnType() { return colType; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterator wrapper for {@code Table}. * * @param table the collection, not null * @param declaredType the declared type, not null * @param rowType the row type, not null * @param colType the col type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator table( Table table, Class declaredType, Class rowType, Class colType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = table.cellSet().iterator(); private Cell current; @Override public String metaTypeName() { return "Table"; } @Override public boolean metaTypeRequired() { return !Table.class.isAssignableFrom(declaredType); } @Override public SerCategory category() { return SerCategory.TABLE; } @Override public int size() { return table.size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = (Cell) it.next(); } @Override public Class keyType() { return rowType; } @Override public Object key() { return current.getRowKey(); } @Override public Class columnType() { return colType; } @Override public Object column() { return current.getColumnKey(); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } @Override public Object value() { return current.getValue(); } }; } /** * Gets an iterator wrapper for {@code BiMap}. * * @param map the collection, not null * @param declaredType the declared type, not null * @param keyType the value type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator biMap( BiMap map, Class declaredType, Class keyType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = map.entrySet().iterator(); private Entry current; @Override public String metaTypeName() { return "BiMap"; } @Override public boolean metaTypeRequired() { // hack around Guava annoyance by assuming that size 0 and 1 ImmutableBiMap // was actually meant to be an ImmutableMap if ((declaredType == Map.class || declaredType == ImmutableMap.class) && map.size() < 2) { return false; } return !BiMap.class.isAssignableFrom(declaredType); } @Override public SerCategory category() { return SerCategory.MAP; } @Override public int size() { return map.size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = (Entry) it.next(); } @Override public Class keyType() { return keyType; } @Override public Object key() { return current.getKey(); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } @Override public Object value() { return current.getValue(); } }; } /** * Gets an iterable wrapper for {@code ImmutableList}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable immutableList(Class valueType, List> valueTypeTypes) { List coll = new ArrayList<>(); return new SerIterable() { @Override public SerIterator iterator() { return collection(coll, Object.class, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } for (var i = 0; i < count; i++) { coll.add(value); } } @Override public Object build() { return ImmutableList.copyOf(coll); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterable wrapper for {@code ImmutableSortedSet}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable immutableSortedSet(Class valueType, List> valueTypeTypes) { Set coll = new LinkedHashSet<>(); return new SerIterable() { @Override public SerIterator iterator() { return collection(coll, Object.class, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } for (var i = 0; i < count; i++) { coll.add(value); } } @Override public Object build() { return ImmutableSortedSet.copyOf(coll); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterable wrapper for {@code ImmutableSet}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable immutableSet(Class valueType, List> valueTypeTypes) { Set coll = new LinkedHashSet<>(); return new SerIterable() { @Override public SerIterator iterator() { return collection(coll, Object.class, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } for (var i = 0; i < count; i++) { coll.add(value); } } @Override public Object build() { return ImmutableSet.copyOf(coll); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } static SerIterable immutableMap(Class keyType, Class valueType, List> valueTypeTypes) { Map map = new LinkedHashMap<>(); return new SerIterable() { @Override public SerIterator iterator() { return map(map, Object.class, keyType, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key == null) { throw new IllegalArgumentException("Missing key"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } map.put(key, value); } @Override public Object build() { return ImmutableMap.copyOf(map); } @Override public SerCategory category() { return SerCategory.MAP; } @Override public Class keyType() { return keyType; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } static SerIterable immutableSortedMap(Class keyType, Class valueType, List> valueTypeTypes) { Map map = new LinkedHashMap<>(); return new SerIterable() { @Override public SerIterator iterator() { return map(map, Object.class, keyType, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key == null) { throw new IllegalArgumentException("Missing key"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } map.put(key, value); } @Override public Object build() { return ImmutableSortedMap.copyOf(map); } @Override public SerCategory category() { return SerCategory.MAP; } @Override public Class keyType() { return keyType; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } } ================================================ FILE: src/main/java/org/joda/beans/ser/JodaBeanMimeType.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Provides mime types for Joda-Beans. */ public final class JodaBeanMimeType { /** * Mime type for the binary format. */ public static final String BINARY = "application/vnd.org.joda.bean"; /** * Mime type for the XML format. */ public static final String XML = "application/vnd.org.joda.bean+xml"; /** * Mime type for the JSON format. */ public static final String JSON = "application/vnd.org.joda.bean+json"; /** * Restricted constructor */ private JodaBeanMimeType() { } } ================================================ FILE: src/main/java/org/joda/beans/ser/JodaBeanSer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.Set; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.ser.bin.JodaBeanBinFormat; import org.joda.beans.ser.bin.JodaBeanBinReader; import org.joda.beans.ser.bin.JodaBeanBinWriter; import org.joda.beans.ser.json.JodaBeanJsonNumberFormat; import org.joda.beans.ser.json.JodaBeanJsonReader; import org.joda.beans.ser.json.JodaBeanJsonWriter; import org.joda.beans.ser.json.JodaBeanSimpleJsonReader; import org.joda.beans.ser.json.JodaBeanSimpleJsonWriter; import org.joda.beans.ser.map.JodaBeanSimpleMapReader; import org.joda.beans.ser.map.JodaBeanSimpleMapWriter; import org.joda.beans.ser.xml.JodaBeanXmlReader; import org.joda.beans.ser.xml.JodaBeanXmlWriter; import org.joda.convert.StringConvert; /** * Provides the ability for a Joda-Bean to be serialized. *

* Serialization of Joda-Beans uses the information in the beans to optimize * the size of the data output. */ public final class JodaBeanSer { /** * Obtains the singleton compact instance. */ public static final JodaBeanSer COMPACT = new JodaBeanSer("", "", StringConvert.create(), SerIteratorFactory.INSTANCE, true, SerDeserializers.INSTANCE, false, Set.of(), JodaBeanJsonNumberFormat.STRING); /** * Obtains the singleton pretty-printing instance. */ public static final JodaBeanSer PRETTY = new JodaBeanSer(" ", "\n", StringConvert.create(), SerIteratorFactory.INSTANCE, true, SerDeserializers.INSTANCE, false, Set.of(), JodaBeanJsonNumberFormat.STRING); /** * The indent to use. */ private final String indent; /** * The new line to use. */ private final String newLine; /** * The string converter to use. */ private final StringConvert converter; /** * The iterator factory to use. */ private final SerIteratorFactory iteratorFactory; /** * Whether to use short types. */ private final boolean shortTypes; /** * The deserializers. */ private final SerDeserializers deserializers; /** * Whether to include derived properties. */ private final boolean includeDerived; /** * The set of bean classes that are to be treated as values, caching by reference where possible. * Types convertible by Joda-Convert are always treated as value classes. * Note that most serializers do not cache by reference. */ private final Set> beanValueClasses; /** * The JSON number format. */ private final JodaBeanJsonNumberFormat jsonNumberFormat; /** * Creates an instance. * * @param indent the indent, not null * @param newLine the new line, not null * @param converter the converter, not null * @param iteratorFactory the iterator factory, not null * @param shortTypes whether to use short types * @param deserializers the deserializers to use, not null * @param beanValueClasses the bean value classes, not null * @param jsonNumberFormat the JSON number format, not null */ private JodaBeanSer(String indent, String newLine, StringConvert converter, SerIteratorFactory iteratorFactory, boolean shortTypes, SerDeserializers deserializers, boolean includeDerived, Set> beanValueClasses, JodaBeanJsonNumberFormat jsonNumberFormat) { this.indent = indent; this.newLine = newLine; this.converter = converter; this.iteratorFactory = iteratorFactory; this.shortTypes = shortTypes; this.deserializers = deserializers; this.includeDerived = includeDerived; this.beanValueClasses = Set.copyOf(beanValueClasses); this.jsonNumberFormat = jsonNumberFormat; } //----------------------------------------------------------------------- /** * Gets the pretty print indent. * * @return the indent, not null */ public String getIndent() { return indent; } /** * Returns a copy of this serializer with the specified pretty print indent. * * @param indent the indent, not null * @return a copy of this object with the indent changed, not null */ public JodaBeanSer withIndent(String indent) { JodaBeanUtils.notNull(indent, "indent"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } /** * Gets the new line string. * * @return the newLine, not null */ public String getNewLine() { return newLine; } /** * Returns a copy of this serializer with the specified pretty print new line. * * @param newLine the new line, not null * @return a copy of this object with the new line changed, not null */ public JodaBeanSer withNewLine(String newLine) { JodaBeanUtils.notNull(newLine, "newLine"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } /** * Gets the string converter. *

* The default converter can be modified. * * @return the converter, not null */ public StringConvert getConverter() { return converter; } /** * Returns a copy of this serializer with the specified string converter. *

* The default converter can be modified. * * @param converter the converter, not null * @return a copy of this object with the converter changed, not null */ public JodaBeanSer withConverter(StringConvert converter) { JodaBeanUtils.notNull(converter, "converter"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } /** * Gets the iterator factory. * * @return the iterator factory, not null */ public SerIteratorFactory getIteratorFactory() { return iteratorFactory; } /** * Returns a copy of this serializer with the specified iterator factory. * * @param iteratorFactory the iterator factory, not null * @return a copy of this object with the iterator factory changed, not null */ public JodaBeanSer withIteratorFactory(SerIteratorFactory iteratorFactory) { JodaBeanUtils.notNull(iteratorFactory, "iteratorFactory"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } /** * Gets whether to use short types. * * @return the short types flag, not null */ public boolean isShortTypes() { return shortTypes; } /** * Returns a copy of this serializer with the short types flag set. * * @param shortTypes whether to use short types, not null * @return a copy of this object with the short types flag changed, not null */ public JodaBeanSer withShortTypes(boolean shortTypes) { return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } /** * Gets the deserializers. *

* The default deserializers can be modified. * * @return the converter, not null */ public SerDeserializers getDeserializers() { return deserializers; } /** * Returns a copy of this serializer with the specified deserializers. *

* The default deserializers can be modified. *

* This can be used to select a more lenient mode of parsing, see {@link SerDeserializers#LENIENT}. * * @param deserializers the deserializers, not null * @return a copy of this object with the converter changed, not null */ public JodaBeanSer withDeserializers(SerDeserializers deserializers) { JodaBeanUtils.notNull(deserializers, "deserializers"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } //----------------------------------------------------------------------- /** * Gets the include derived flag. *

* The default deserializers can be modified. * * @return the converter, not null */ public boolean isIncludeDerived() { return includeDerived; } /** * Returns a copy of this serializer with the specified include derived flag. *

* The default deserializers can be modified. *

* This is used to set the output to include derived properties. * * @param includeDerived whether to include derived properties on output * @return a copy of this object with the derived flag changed, not null */ public JodaBeanSer withIncludeDerived(boolean includeDerived) { return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } //----------------------------------------------------------------------- /** * Gets the bean value classes. * * @return the bean value classes, not null * @since 3.0.0 */ public Set> getBeanValueClasses() { return beanValueClasses; } /** * Returns a copy of this serializer with the bean value classes changed. * * @param beanValueClasses the bean value classes, not null * @return a copy of this object with the bean value classes changed, not null * @since 3.0.0 */ public JodaBeanSer withBeanValueClasses(Set> beanValueClasses) { JodaBeanUtils.notNull(beanValueClasses, "beanValueClasses"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } //----------------------------------------------------------------------- /** * Gets the JSON number format. * * @return the JSON number format, not null * @since 3.0.0 */ public JodaBeanJsonNumberFormat getJsonNumberFormat() { return jsonNumberFormat; } /** * Returns a copy of this serializer with the JSON number format changed. * * @param jsonNumberFormat the JSON number format, not null * @return a copy of this object with the bean value classes changed, not null * @since 3.0.0 */ public JodaBeanSer withJsonNumberFormat(JodaBeanJsonNumberFormat jsonNumberFormat) { JodaBeanUtils.notNull(jsonNumberFormat, "jsonNumberFormat"); return new JodaBeanSer( indent, newLine, converter, iteratorFactory, shortTypes, deserializers, includeDerived, beanValueClasses, jsonNumberFormat); } //------------------------------------------------------------------------- /** * Checks if the property is serialized. * * @param prop the property to check * @return true if the property is serialized */ public boolean isSerialized(MetaProperty prop) { return prop.style().isSerializable() || (prop.style().isDerived() && includeDerived); } //----------------------------------------------------------------------- /** * Creates a reader that determines the file format and parses it. *

* This parser can handle XML, JSON, simple JSON, binary and binary referencing formats. *

* It is recommended, though not necessary, to create a new instance of the reader for each message. * * @return the smart reader, not null */ public JodaBeanSmartReader smartReader() { return new JodaBeanSmartReader(this); } //----------------------------------------------------------------------- /** * Creates a binary writer using the standard format. *

* It is recommended, though not necessary, to create a new instance of the writer for each message. * * @return the binary writer, not null */ public JodaBeanBinWriter binWriter() { return new JodaBeanBinWriter(this, JodaBeanBinFormat.STANDARD); } /** * Creates a binary writer using the specified format. *

* It is recommended, though not necessary, to create a new instance of the writer for each message. * * @param format the format, not null * @return the binary writer, not null * @since 3.0.0 */ public JodaBeanBinWriter binWriter(JodaBeanBinFormat format) { return new JodaBeanBinWriter(this, format); } /** * Creates a binary writer using the referencing format that typically results in a smaller output. *

* It is recommended, though not necessary, to create a new instance of the writer for each message. *

* The writer only supports serializing ImmutableBean instances and will throw an exception * if any non-immutable beans are encountered. * It assumes that non-bean items present within the root bean are themselves immutable. * Due to this immutability restriction it serializes references to values based on object equality, * rather than based on reference equality. When the output is parsed it may be smaller in memory * as any beans that were originally equal will be returned as pointers to the same instance. *

* The reader {@link #binReader()} handles both the standard and referencing formats. * * @return the referencing binary writer, not null * @deprecated Pass the format explicitly */ @Deprecated public JodaBeanBinWriter binWriterReferencing() { return new JodaBeanBinWriter(this, JodaBeanBinFormat.REFERENCING); } /** * Creates a binary reader that handles all binary formats that can be written. *

* It is recommended, though not necessary, to create a new instance of the reader for each message. * * @return the binary reader, not null */ public JodaBeanBinReader binReader() { return new JodaBeanBinReader(this); } //----------------------------------------------------------------------- /** * Creates an XML writer. *

* A new instance of the writer must be created for each message. * * @return the XML writer, not null */ public JodaBeanXmlWriter xmlWriter() { return new JodaBeanXmlWriter(this); } /** * Creates an XML reader. *

* A new instance of the reader must be created for each message. * * @return the XML reader, not null */ public JodaBeanXmlReader xmlReader() { return new JodaBeanXmlReader(this); } //----------------------------------------------------------------------- /** * Creates a JSON writer. *

* A new instance of the writer must be created for each message. * * @return the JSON writer, not null */ public JodaBeanJsonWriter jsonWriter() { return new JodaBeanJsonWriter(this); } /** * Creates a JSON reader. *

* A new instance of the reader must be created for each message. * * @return the JSON reader, not null */ public JodaBeanJsonReader jsonReader() { return new JodaBeanJsonReader(this); } //----------------------------------------------------------------------- /** * Creates a simple JSON writer. *

* A new instance of the writer must be created for each message. * The simple writer omits all metadata. * It is suitable for simple beans as often found in data-transfer protocols. *

* Not all beans can be used with the simple JSON writer as no type information is written. * If a bean has subclasses, or the declared type of a property or collection is * {@code Object}, then the JSON will not round trip. Where the type cannot be determined, * the reader will return {@code Boolean}, {@code Integer}, {@code Double}, {@code String}, * {@code ArrayList} or string keyed {@code HashMap}. * Maps must have keys that can be written as a string. * * @return the simple JSON writer, not null */ public JodaBeanSimpleJsonWriter simpleJsonWriter() { return new JodaBeanSimpleJsonWriter(this); } /** * Creates a simple JSON reader. *

* A new instance of the reader must be created for each message. * The simple reader is designed to operate with the simple writer. * It will not operate well with the output of {@link #jsonWriter()}. * * @return the simple JSON reader, not null */ public JodaBeanSimpleJsonReader simpleJsonReader() { return new JodaBeanSimpleJsonReader(this); } //----------------------------------------------------------------------- /** * Creates a simple in-memory {@code Map} writer. *

* A new instance of the writer must be created for each message. * * @return the simple map writer, not null */ public JodaBeanSimpleMapWriter simpleMapWriter() { return new JodaBeanSimpleMapWriter(this); } /** * Creates a simple in-memory {@code Map} reader. *

* A new instance of the reader must be created for each message. * * @return the simple map reader, not null */ public JodaBeanSimpleMapReader simpleMapReader() { return new JodaBeanSimpleMapReader(this); } //----------------------------------------------------------------------- @Override public String toString() { return getClass().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/ser/JodaBeanSerFormat.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; /** * The Joda-Beans serialization format. */ enum JodaBeanSerFormat { /** * The binary format. */ BIN , /** * The JSON format. */ JSON, /** * The JSON format. */ JSON_UTF8, /** * The XML format. */ XML, /** * The XML format. */ XML_UTF8, /** * The format is unknown. */ UNKNOWN; // creates the reader, handling any UTF BOM T read(InputStream stream, Class rootType, JodaBeanSer settings) { // javac generics fails when this code is moved to enum subclasses return switch (this) { case BIN -> settings.binReader().read(stream, rootType); case JSON -> { var reader = new InputStreamReader(stream, StandardCharsets.UTF_8); yield rootType.cast(settings.simpleJsonReader().read(reader, rootType)); } case JSON_UTF8 -> { read(stream, 3); var reader = new InputStreamReader(stream, StandardCharsets.UTF_8); yield rootType.cast(settings.simpleJsonReader().read(reader, rootType)); } case XML -> { var reader = new InputStreamReader(stream, StandardCharsets.UTF_8); yield rootType.cast(settings.xmlReader().read(reader, rootType)); } case XML_UTF8 -> { read(stream, 3); var reader = new InputStreamReader(stream, StandardCharsets.UTF_8); yield rootType.cast(settings.xmlReader().read(reader, rootType)); } case UNKNOWN -> throw new IllegalArgumentException("File is not a recognised Joda-Beans format"); default -> throw new IllegalArgumentException("File is not a recognised Joda-Beans format"); }; } // read a fixed number of bytes from the input stream private static void read(InputStream buffered, int count) { try { for (var i = 0; i < count; i++) { buffered.read(); } } catch (IOException ex) { throw new UncheckedIOException(ex); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/JodaBeanSmartReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; /** * Determines the correct file format and parses it appropriately. */ public class JodaBeanSmartReader { /** * The settings. */ private final JodaBeanSer settings; /** * Creates an instance. * * @param settings the settings, not null */ JodaBeanSmartReader(JodaBeanSer settings) { this.settings = settings; } //----------------------------------------------------------------------- /** * Checks if the input is a serialized Joda-Bean. *

* XML and JSON files may be prefixed by the UTF-8 Unicode BOM. *

* Callers may pass in part of the file, rather than the whole file. * Up to 128 bytes are needed to determine the format (XML requires the most, others far less). * * @param input the input bytes to check, which need only consist of the first 128 bytes of the file, not null * @return true if it is a known format */ public boolean isKnownFormat(byte[] input) { return determineFormat(input) != JodaBeanSerFormat.UNKNOWN; } /** * Checks if the input is a serialized Joda-Bean. *

* XML and JSON files may be prefixed by the UTF-8 Unicode BOM. *

* The input stream will be marked and reset, thus these operations must be supported. * As such, the same stream can then be for parsing. * * @param input the input stream to check, where only the first few bytes are read, not null * @return true if it is a known format * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if the input stream does not support mark/reset */ public boolean isKnownFormat(InputStream input) { return determineFormat(input) != JodaBeanSerFormat.UNKNOWN; } //----------------------------------------------------------------------- // determines the format of a serialized Joda-Bean private JodaBeanSerFormat determineFormat(byte[] input) { if (input.length < 2) { return JodaBeanSerFormat.UNKNOWN; } // parse each known format. including possible UTF BOM prefix if (input.length >= 4 && input[0] == (byte) 0xef && input[1] == (byte) 0xbb && input[2] == (byte) 0xbf) { if (input[3] == '<' && isXml(input, 3)) { return JodaBeanSerFormat.XML_UTF8; } else if (input[3] == '{' && isJson(input, 3)) { return JodaBeanSerFormat.JSON_UTF8; } else { return JodaBeanSerFormat.UNKNOWN; } } else if (input[0] == '<' && isXml(input, 0)) { return JodaBeanSerFormat.XML; } else if (input[0] == '{' && isJson(input, 0)) { return JodaBeanSerFormat.JSON; } else if (input[0] == (byte) 0x94 && input[1] == (byte) 0x02) { return JodaBeanSerFormat.BIN; } else if (input[0] == (byte) 0x92 && input[1] == (byte) 0x01) { return JodaBeanSerFormat.BIN; } else { return JodaBeanSerFormat.UNKNOWN; } } private boolean isXml(byte[] bytes, int pos) { var str = new String(bytes, pos, bytes.length - pos, StandardCharsets.UTF_8); return str.contains(""); } private boolean isJson(byte[] bytes, int pos) { for (var i = pos + 1; i < bytes.length; i++) { var b = bytes[i]; if (b == '}' || b == '"') { return true; } else if (!(b == ' ' || b == '\t' || b == '\r' || b == '\n')) { return false; } } return false; } // determines the format of a serialized Joda-Bean private JodaBeanSerFormat determineFormat(InputStream input) { if (!input.markSupported()) { throw new IllegalArgumentException("Input stream does not support mark/reset"); } var buf = new byte[128]; try { input.mark(128); var readCount = read(input, buf, 128); buf = Arrays.copyOf(buf, readCount); input.reset(); } catch (IOException ex) { throw new UncheckedIOException(ex); } return determineFormat(buf); } // fully reads the stream private static int read(InputStream in, byte[] buf, int len) throws IOException { var pos = 0; while (pos < len) { var result = in.read(buf, pos, len - pos); if (result == -1) { break; } pos += result; } return pos; } //----------------------------------------------------------------------- /** * Reads and parses to a bean. *

* XML and JSON files may be prefixed by the UTF-8 Unicode BOM. * * @param input the input bytes to parse, not null * @return the bean, not null * @throws IllegalArgumentException if the file format is not recognized * @throws RuntimeException if unable to parse */ public Bean read(byte[] input) { return read(input, Bean.class); } /** * Reads and parses to a bean. *

* XML and JSON files may be prefixed by the UTF-8 Unicode BOM. * * @param the root type * @param input the input bytes to parse, not null * @param rootType the root type, not null * @return the bean, not null * @throws IllegalArgumentException if the file format is not recognized * @throws RuntimeException if unable to parse */ public T read(byte[] input, Class rootType) { JodaBeanUtils.notNull(input, "input"); return read(new ByteArrayInputStream(input), rootType); } /** * Reads and parses to a bean. *

* XML and JSON files may be prefixed by the UTF-8 Unicode BOM. * * @param input the input stream, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if the file format is not recognized * @throws RuntimeException if unable to parse */ public Bean read(InputStream input) { return read(input, Bean.class); } /** * Reads and parses to a bean. *

* XML and JSON files may be prefixed by the UTF-8 Unicode BOM. * * @param the root type * @param input the input stream, not null * @param rootType the root type, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if the file format is not recognized * @throws RuntimeException if unable to parse */ public T read(InputStream input, Class rootType) { JodaBeanUtils.notNull(input, "input"); JodaBeanUtils.notNull(rootType, "rootType"); var buffered = buffer(input); var format = determineFormat(buffered); return format.read(buffered, rootType, settings); } // buffer the input stream private BufferedInputStream buffer(InputStream input) { if (input.getClass() == BufferedInputStream.class) { return (BufferedInputStream) input; } return new BufferedInputStream(input); } } ================================================ FILE: src/main/java/org/joda/beans/ser/LenientDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.NoSuchElementException; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; /** * Lenient deserializer that ignores unknown properties. */ class LenientDeserializer extends DefaultDeserializer { /** * Singleton. */ public static final SerDeserializer INSTANCE = new LenientDeserializer(); /** * Creates an instance. */ protected LenientDeserializer() { } //----------------------------------------------------------------------- @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { // dynamic beans force code by exception try { return metaBean.metaProperty(propertyName); } catch (NoSuchElementException ex) { return null; } } } ================================================ FILE: src/main/java/org/joda/beans/ser/LinkedByteArrayOutputStream.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.HexFormat; import java.util.Objects; /** * An optimised byte array output stream. *

* This class holds a number of smaller byte arrays internally. * Each array is typically 1024 bytes, but if a large byte array is written * the class will hold it as a single large array. *

* Calling {@link #toByteArray()} returns a single combined byte array. * Calling {@link #writeTo(OutputStream)} writes the internal arrays without needing to create a combined array. *

* This class is not thread-safe. */ public class LinkedByteArrayOutputStream extends OutputStream { // segment holding one byte array, the current position in the array, and the next segment when it is full private static final class ByteSegment { private final byte[] bytes; private int pos; private ByteSegment next; private ByteSegment(byte[] bytes) { this.bytes = bytes; } } // the head/root segment private final ByteSegment head = new ByteSegment(new byte[1024]); // the current tail private ByteSegment tail = head; // the total number of bytes written private int total; /** * Creates an instance. */ public LinkedByteArrayOutputStream() { } //------------------------------------------------------------------------- /** * Writes a single byte to the output stream. * * @param val the value */ @Override public void write(int val) { var tailRemaining = tail.bytes.length - tail.pos; if (tailRemaining == 0) { tail.next = new ByteSegment(new byte[1024]); tail = tail.next; } tail.bytes[tail.pos] = (byte) val; tail.pos++; total++; } /** * Writes all or part of a byte array to the output stream. * * @param bytes the byte array to write, not null * @param offset the offset from the start of the array * @param length the number of bytes to write * @throws IndexOutOfBoundsException if the offset or length is invalid */ @Override public void write(byte[] bytes, int offset, int length) { Objects.checkFromIndexSize(offset, length, bytes.length); var tailRemaining = tail.bytes.length - tail.pos; // first part var firstPartLength = Math.min(tailRemaining, length); System.arraycopy(bytes, offset, tail.bytes, tail.pos, firstPartLength); tail.pos += firstPartLength; // remainder var newLength = length - firstPartLength; if (newLength > 0) { var newOffset = offset + firstPartLength; if (newLength >= 1024) { tail.next = new ByteSegment(Arrays.copyOfRange(bytes, newOffset, length)); } else { tail.next = new ByteSegment(new byte[1024]); System.arraycopy(bytes, newOffset, tail.next.bytes, 0, newLength); } tail = tail.next; tail.pos = newLength; } total += length; } /** * Writes a byte array to the output stream. * * @param bytes the byte array to write, not null */ @Override public void write(byte[] bytes) { write(bytes, 0, bytes.length); } /** * Writes all the bytes to the specified output stream. * * @param out the output stream to write to * @throws IOException if an IO error occurs */ public void writeTo(OutputStream out) throws IOException { for (var segment = head; segment != null; segment = segment.next) { out.write(segment.bytes, 0, segment.pos); } } /** * Returns a single byte array containing all the bytes written to the output stream. *

* The returned array contains a copy of the internal state of this class. *

* It is not expected that callers will call this method multiple times, although it is safe to do so. * * @return the combined byte array */ public byte[] toByteArray() { var result = new byte[total]; var pos = 0; for (var segment = head; segment != null; segment = segment.next) { System.arraycopy(segment.bytes, 0, result, pos, segment.pos); pos += segment.pos; } return result; } /** * Gets the current number of bytes written. * * @return the number of bytes written */ public int size() { return total; } /** * A no-op, as this class does not need flushing. */ @Override public void flush() { } /** * A no-op, as this class does not need closing. */ @Override public void close() { } /** * Returns a hex-formatted string of the bytes that have been written. */ @Override public String toString() { var hex = HexFormat.of(); var buf = new StringBuilder(total * 2); for (var segment = head; segment != null; segment = segment.next) { hex.formatHex(buf, segment.bytes, 0, segment.pos); } return buf.toString(); } } ================================================ FILE: src/main/java/org/joda/beans/ser/SerCategory.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Defines the type of the iterable. */ public enum SerCategory { /** * Simple collection. */ COLLECTION, /** * Counted collection. */ COUNTED, /** * Map. */ MAP, /** * Table. */ TABLE, /** * Grid. */ GRID; } ================================================ FILE: src/main/java/org/joda/beans/ser/SerDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; /** * Assists with deserialization allowing migration of data from an old data format to a new one. *

* This allows beans stored under an old version to be read in by a newer version. *

* Methods are called in order as follows: *

    *
  1. {@code lookupMetaBean} *
  2. {@code createBuilder} *
  3. {@code lookupMetaProperty}, then {@code setValue} - once per property *
  4. {@code build} *
*

* A renamed property can be handled by overriding the {@code lookupMetaProperty}: *

 *  public MetaProperty<?> findMetaProperty(Class<?> beanType, MetaBean metaBean, String propertyName) {
 *    if ("firstName".equals(propertyName)) {
 *      return metaBean.metaProperty("forename");
 *    }
 *    return super.findMetaProperty(beanType, metaBean, propertyName);
 *  }
 * 
*

* A property type change can be handled by overriding the {@code lookupMetaProperty} * and {@code setValue}: *

 *  private MetaProperty<String> NUMBER_OF_CARS_STRING =
 *    StandaloneMetaProperty.of("numberOfCars", SimplePerson.meta(), String.class);
 *  
 *  public MetaProperty<?> findMetaProperty(Class<?> beanType, MetaBean metaBean, String propertyName) {
 *    if ("numberOfCars".equals(propertyName)) {
 *      return NUMBER_OF_CARS_STRING;  // replica of the old property
 *    }
 *    return super.findMetaProperty(beanType, metaBean, propertyName);
 *  }
 *
 *  public void setValue(BeanBuilder builder, MetaProperty metaProp, Object value) {
 *    if (metaProp == NUMBER_OF_CARS_STRING && value != null) {
 *      String oldValue = value.toString();
 *      switch (oldValue) {
 *        case "One": value = 1; break;
 *        case "Two": value = 2; break;
 *        case "Lots": value = 3; break;
 *        default: value = 0; break;
 *      }
 *    }
 *    super.setValue(builder, metaProp, value);
 *  }
 * 
*

* A semantic change can be handled by overriding the {@code createBuilder} * and {@code build}, buffering the input to process at the end of the bean: *

 *  public BeanBuilder createBuilder(Class beanType, MetaBean metaBean) {
 *    return BufferingBeanBuilder.of(metaBean);
 *  }
 *
 *  public Object build(Class<?> beanType, BeanBuilder<?> builder) {
 *    BufferingBeanBuilder<?> bld = (BufferingBeanBuilder<?>) builder;
 *    if ("Stephen".equals(bld.getBuffer().get(SimplePerson.meta().forename())) &&
 *         "Colebourne".equals(bld.getBuffer().get(SimplePerson.meta().surname()))) {
 *      bld.set(SimplePerson.meta().forename(), "Steve");
 *    }
 *    return bld.build();
 *  }
 * 
*/ public interface SerDeserializer { /** * Lookup the meta-bean for the specified type. *

* If the type is not a bean, then null may be returned. * * @param beanType the type being processed, not null * @return the meta-bean, null if not a bean type */ public abstract MetaBean findMetaBean(Class beanType); /** * Creates the stateful builder that captures state as the parse progresses. *

* This is normally a {@code BeanBuilder} however any type may be returned. * * @param beanType the type being processed, not null * @param metaBean the meta-bean, null if not a bean type * @return the builder, null if not interested in the parse progress */ public abstract BeanBuilder createBuilder(Class beanType, MetaBean metaBean); /** * Lookup the meta-property for the specified property name. *

* Return null if a property has been deleted, which will cause the parser * to discard the property. *

* Return a non-null meta-property to parse the property. * If the property was renamed, or had a type change, then the meta-property * should match the property as originally stored. * * @param beanType the type being processed, not null * @param metaBean the meta-bean, null if not a bean type * @param propertyName the property name being parsed, not null * @return the meta-property, null to ignore the property */ public abstract MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName); /** * Sets the parsed value into the builder. * * @param builder the builder, null if not interested in the parse progress * @param metaProp the meta-property, not null * @param value the parsed value, may be null */ public abstract void setValue(BeanBuilder builder, MetaProperty metaProp, Object value); /** * Builds the resulting object. *

* This method finishes the builder and returns the final object. * The migrator could validate or manipulate data here once all data is parsed, * for example to default a missing field. * * @param beanType the type being processed, not null * @param builder the builder, null if not interested in the parse progress * @return the final built object, may be null */ public abstract Object build(Class beanType, BeanBuilder builder); } ================================================ FILE: src/main/java/org/joda/beans/ser/SerDeserializerProvider.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Provides access to deserializers. *

* This plugin point allows instances to {@link SerDeserializer} to be created. * Implementations of this interface can introspect the bean type when choosing a deserializer. * This allows deserializers to be provided that can handle multiple bean types, for example all beans * in a particular package, any bean with a particular supertype or with a particular annotation. *

* In the simple case where an exact match is needed, the class implementing {@link SerDeserializer} * can also implement {@link SerDeserializerProvider} with a singleton constant instance. */ public interface SerDeserializerProvider { /** * Finds the deserializer for the specified type. *

* If the type is not known, the implementation must return null. * * * @param beanType the type being processed, not null * @return the deserializer, null if this provider does not support the type */ public abstract SerDeserializer findDeserializer(Class beanType); } ================================================ FILE: src/main/java/org/joda/beans/ser/SerDeserializers.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.URL; import java.util.AbstractMap.SimpleEntry; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.convert.RenameHandler; /** * Manages a map of deserializers that assist with data migration. *

* Deserializers handle situations where the data being read does not match the * bean in the classpath. See also {@code RenameHandler}. *

* Normally, it makes sense to customize the shared singleton instance, because * the classpath is static and fixed and the transformations are common. *

* Implementations must be thread-safe singletons. */ public final class SerDeserializers { /** * Deserializers loaded from the classpath. */ private static final Map, SerDeserializer> CLASSPATH_STRICT = loadFromClasspath(); /** * Deserializers loaded from the classpath. */ private static final Map, SerDeserializer> CLASSPATH_LENIENT = CLASSPATH_STRICT.entrySet().stream() .map(e -> new SimpleEntry<>(e.getKey(), toLenient(e.getValue()))) .collect(toMap(e -> e.getKey(), e -> e.getValue())); /** * Shared global instance which can be mutated. */ public static final SerDeserializers INSTANCE = new SerDeserializers(false); /** * Lenient instance which can be mutated. */ public static final SerDeserializers LENIENT = new SerDeserializers(true); /** * Whether deserialization is lenient. */ private final boolean lenient; /** * The default deserializer. */ private final SerDeserializer defaultDeserializer; /** * The deserializers. */ private final ConcurrentMap, SerDeserializer> deserializers = new ConcurrentHashMap<>(); /** * The deserializer providers. */ private final CopyOnWriteArrayList providers = new CopyOnWriteArrayList<>(); /** * Creates an instance. */ public SerDeserializers() { this.lenient = false; this.defaultDeserializer = DefaultDeserializer.INSTANCE; this.deserializers.putAll(CLASSPATH_STRICT); } /** * Creates an instance using additional providers. * * @param providers the providers to use */ public SerDeserializers(SerDeserializerProvider... providers) { this(false, providers); } /** * Creates an instance using additional providers. * * @param lenient whether to deserialize leniently * @param providers the providers to use */ public SerDeserializers(boolean lenient, SerDeserializerProvider... providers) { this.lenient = lenient; this.defaultDeserializer = lenient ? LenientDeserializer.INSTANCE : DefaultDeserializer.INSTANCE; this.deserializers.putAll(lenient ? CLASSPATH_LENIENT : CLASSPATH_STRICT); this.providers.addAll(Arrays.asList(providers)); } //----------------------------------------------------------------------- /** * Adds the deserializer to be used for the specified type. * * @param type the type, not null * @param deserializer the deserializer, not null * @return this, for chaining, not null */ public SerDeserializers register(Class type, SerDeserializer deserializer) { deserializers.put(type, deserializer); return this; } /** * Gets the map of deserializers which can be modified. * * @return the map of deserializers, not null */ public ConcurrentMap, SerDeserializer> getDeserializers() { return deserializers; } //----------------------------------------------------------------------- /** * Adds the deserializer provider to be used. * * @param provider the deserializer provider, not null * @return this, for chaining, not null */ public SerDeserializers registerProvider(SerDeserializerProvider provider) { providers.add(provider); return this; } //----------------------------------------------------------------------- /** * Finds the deserializer for the specified type. *

* The {@code DefaultDeserializer} is used if one has not been registered. * * @param type the type, not null * @return the deserializer, not null */ public SerDeserializer findDeserializer(Class type) { var deser = deserializers.get(type); if (deser != null) { return deser; } for (SerDeserializerProvider provider : providers) { deser = provider.findDeserializer(type); if (deser != null) { return deser; } } return defaultDeserializer; } /** * Decodes the type * * @param typeStr the type, not null * @param settings the settings, not null * @param basePackage the base package, not null * @param knownTypes the known types, not null * @param defaultType the default type, not null * @return the decoded type * @throws ClassNotFoundException if the class is not found */ public Class decodeType( String typeStr, JodaBeanSer settings, String basePackage, Map> knownTypes, Class defaultType) throws ClassNotFoundException { if (lenient) { return SerTypeMapper.decodeType( typeStr, settings, basePackage, knownTypes, defaultType == Object.class ? String.class : defaultType); } return SerTypeMapper.decodeType(typeStr, settings, basePackage, knownTypes); } //----------------------------------------------------------------------- // loads config files private static Map, SerDeserializer> loadFromClasspath() { // log errors to System.err, as problems in static initializers can be troublesome to diagnose Map, SerDeserializer> result = new HashMap<>(); URL url = null; try { // this is the new location of the file, working on Java 8, Java 9 class path and Java 9 module path var loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { loader = RenameHandler.class.getClassLoader(); } var en = loader.getResources("META-INF/org/joda/beans/JodaBeans.ini"); while (en.hasMoreElements()) { url = en.nextElement(); var lines = loadRenameFile(url); parseRenameFile(lines, url, result); } } catch (Error | Exception ex) { System.err.println("ERROR: Unable to load JodaBeans.ini: " + url + ": " + ex.getMessage()); ex.printStackTrace(); result.clear(); } return result; } // loads a single rename file private static List loadRenameFile(URL url) throws IOException { try (var reader = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) { return reader.lines() .filter(line -> !line.isEmpty() && !line.startsWith("#")) .collect(toList()); } } // parses a single rename file private static void parseRenameFile(List lines, URL url, Map, SerDeserializer> map) { // format allows multiple [deserializers] so file can be merged var deserializers = false; for (String line : lines) { try { if (line.equals("[deserializers]")) { deserializers = true; } else if (deserializers) { var equalsPos = line.indexOf('='); var beanName = equalsPos >= 0 ? line.substring(0, equalsPos).trim() : line; var deserName = equalsPos >= 0 ? line.substring(equalsPos + 1).trim() : line; registerFromClasspath(beanName, deserName, map); } else { throw new IllegalArgumentException("JodaBeans.ini must start with [deserializers]"); } } catch (Exception ex) { System.err.println("ERROR: Invalid JodaBeans.ini: " + url + ": " + ex.getMessage()); } } } // parses and registers the classes private static void registerFromClasspath( String beanName, String deserName, Map, SerDeserializer> map) throws Exception { Class beanClass = Class.forName(beanName).asSubclass(Bean.class); Class deserClass = Class.forName(deserName); Field field = null; SerDeserializer deser; try { field = deserClass.getDeclaredField("DESERIALIZER"); if (!Modifier.isStatic(field.getModifiers())) { throw new IllegalStateException("Field " + field + " must be static"); } deser = (SerDeserializer) field.get(null); } catch (NoSuchFieldException ex) { Constructor cons = null; try { cons = deserClass.getConstructor(); deser = (SerDeserializer) cons.newInstance(); } catch (NoSuchMethodException ex2) { throw new IllegalStateException( "Class " + deserClass.getName() + " must have field DESERIALIZER or a no-arg constructor"); } catch (IllegalAccessException ex2) { cons.setAccessible(true); deser = (SerDeserializer) cons.newInstance(); } } catch (IllegalAccessException ex) { field.setAccessible(true); deser = (SerDeserializer) field.get(null); } map.put(beanClass, deser); } // makes the deserializer lenient private static SerDeserializer toLenient(SerDeserializer underlying) { return new SerDeserializer() { @Override public MetaBean findMetaBean(Class beanType) { return underlying.findMetaBean(beanType); } @Override public BeanBuilder createBuilder(Class beanType, MetaBean metaBean) { return underlying.createBuilder(beanType, metaBean); } @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { // dynamic beans force code by exception try { return underlying.findMetaProperty(beanType, metaBean, propertyName); } catch (NoSuchElementException ex) { return null; } } @Override public void setValue(BeanBuilder builder, MetaProperty metaProp, Object value) { underlying.setValue(builder, metaProp, value); } @Override public Object build(Class beanType, BeanBuilder builder) { return underlying.build(beanType, builder); } }; } //----------------------------------------------------------------------- @Override public String toString() { return getClass().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/ser/SerIterable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.List; /** * An abstraction over collections, lists, sets and maps. *

* This is a plugin point that can handle Guava collections. */ public abstract class SerIterable { /** * Obtains an iterator over the data. * * @return the iterator, not null */ public abstract SerIterator iterator(); /** * Sets the dimensions of the wrapped collection. * * @param dimensions the dimension, 0 for row, 1 for column */ public void dimensions(int[] dimensions) { throw new IllegalArgumentException("Iterable does not support dimensions"); } /** * Adds an item to the builder. * * @param key the key, such as for a map, null if no key * @param column the column, such as for a table, null if no column * @param value the value, such as for a map or list value, may be null * @param count the count, such as for a multiset, typically one or greater */ public abstract void add(Object key, Object column, Object value, int count); /** * Builds the final collection. * * @return the build collection, not null */ public abstract Object build(); /** * Gets the category of iterable. * * @return the category, not null */ public SerCategory category() { return SerCategory.COLLECTION; } /** * Gets the type of the key. * * @return the key type, null if no key */ public Class keyType() { return null; } /** * Gets the type of the column. * * @return the column type, null if no column */ public Class columnType() { return null; } /** * Gets the type of the value. * * @return the value type, not null */ public abstract Class valueType(); /** * Gets the generic parameters of the value type. * * @return the generic parameters of the value type, not null */ public abstract List> valueTypeTypes(); } ================================================ FILE: src/main/java/org/joda/beans/ser/SerIterator.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.List; /** * An abstraction of collections, lists, sets and maps. *

* This is a plugin point that can handle Guava collections. */ public abstract class SerIterator { /** * Gets the meta type of the underlying. * * @return the type, such as 'List' or 'Map' */ public abstract String metaTypeName(); /** * Checks if the meta type of the underlying is required. * * @return true if generic inspection is insufficient to determine the collection */ public abstract boolean metaTypeRequired(); /** * Gets the size of one dimension of the wrapped collection. * * @param dimension the dimension, 0 for row, 1 for column * @return the size, -1 if unknown */ public int dimensionSize(int dimension) { return -1; } /** * Gets the size of the wrapped collection. * * @return the size, -1 if unknown */ public abstract int size(); /** * Gets the category of iterable. * * @return the category, not null */ public SerCategory category() { return SerCategory.COLLECTION; } /** * Checks if there is a next item. * * @return true if there is another item */ public abstract boolean hasNext(); /** * Advances to the next item. */ public abstract void next(); /** * Gets the number of occurrences of this item. * * @return the count */ public int count() { return 1; } /** * Gets the type of the key. * * @return the key type, null if no key */ public Class keyType() { return null; } /** * The key. * * @return the key, may be null */ public Object key() { return null; } /** * Gets the type of the column. * * @return the column type, null if no column */ public Class columnType() { return null; } /** * The column. * * @return the key, may be null */ public Object column() { return null; } /** * Gets the type of the value. * * @return the value type, not null */ public abstract Class valueType(); /** * Gets the generic parameters of the value type. * * @return the generic parameters of the value type, not null */ public abstract List> valueTypeTypes(); /** * The value. * * @return the value, may be null */ public abstract Object value(); /** * The value at a row/column. * * @param row the row * @param column the column * @return the value */ public Object value(int row, int column) { return null; } } ================================================ FILE: src/main/java/org/joda/beans/ser/SerIteratorFactory.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NavigableMap; import java.util.NavigableSet; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.collect.grid.ImmutableGrid; import com.google.common.collect.ImmutableMultiset; /** * A factory used to create wrappers around collection-like objects. */ public class SerIteratorFactory { /** * Singleton instance. */ public static final SerIteratorFactory INSTANCE = getInstance(); private static SerIteratorFactory getInstance() { try { ImmutableGrid.of(); // check if class is available return new CollectSerIteratorFactory(); } catch (Exception | LinkageError ex) { try { ImmutableMultiset.of(); // check if class is available return new GuavaSerIteratorFactory(); } catch (Exception | LinkageError ex2) { return new SerIteratorFactory(); } } } /** * An empty list of classes. */ public static final List> EMPTY_VALUE_TYPES = Collections.emptyList(); /** * Map of array types. */ private static final Map> META_TYPE_MAP = new HashMap<>(); static { META_TYPE_MAP.put("Object[]", Object.class); META_TYPE_MAP.put("String[]", String.class); META_TYPE_MAP.put("boolean[]", boolean.class); META_TYPE_MAP.put("char[]", char.class); META_TYPE_MAP.put("byte[]", byte.class); META_TYPE_MAP.put("short[]", short.class); META_TYPE_MAP.put("int[]", int.class); META_TYPE_MAP.put("long[]", long.class); META_TYPE_MAP.put("float[]", float.class); META_TYPE_MAP.put("double[]", double.class); META_TYPE_MAP.put("Object[][]", Object[].class); META_TYPE_MAP.put("String[][]", String[].class); META_TYPE_MAP.put("boolean[][]", boolean[].class); META_TYPE_MAP.put("char[][]", char[].class); META_TYPE_MAP.put("byte[][]", byte[].class); META_TYPE_MAP.put("short[][]", short[].class); META_TYPE_MAP.put("int[][]", int[].class); META_TYPE_MAP.put("long[][]", long[].class); META_TYPE_MAP.put("float[][]", float[].class); META_TYPE_MAP.put("double[][]", double[].class); } //----------------------------------------------------------------------- /** * Creates an iterator wrapper for a meta-property value. * * @param value the possible collection-like object, not null * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @param allowPrimitiveArrays whether to allow primitive arrays * @return the iterator, null if not a collection-like type */ public SerIterator create(Object value, MetaProperty prop, Class beanClass, boolean allowPrimitiveArrays) { if (allowPrimitiveArrays && value.getClass().isArray() && value.getClass().getComponentType().isPrimitive() && value.getClass().getComponentType() != byte.class) { return arrayPrimitive(value, prop.propertyType(), value.getClass().getComponentType()); } return create(value, prop, beanClass); } /** * Creates an iterator wrapper for a meta-property value. * * @param value the possible collection-like object, not null * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @return the iterator, null if not a collection-like type */ public SerIterator create(Object value, MetaProperty prop, Class beanClass) { var declaredType = prop.propertyType(); if (value instanceof Collection collection) { var valueType = defaultToObjectClass(JodaBeanUtils.collectionType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return collection(collection, declaredType, valueType, valueTypeTypes); } if (value instanceof Map map) { var keyType = defaultToObjectClass(JodaBeanUtils.mapKeyType(prop, beanClass)); var valueType = defaultToObjectClass(JodaBeanUtils.mapValueType(prop, beanClass)); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return map(map, declaredType, keyType, valueType, valueTypeTypes); } if (value.getClass().isArray() && !value.getClass().getComponentType().isPrimitive()) { var array = (Object[]) value; return array(array, declaredType, array.getClass().getComponentType()); } return null; } /** * Creates an iterator wrapper for a value retrieved from a parent iterator. *

* Allows the parent iterator to define the child iterator using generic type information. * This handles cases such as a {@code List} as the value in a {@code Map}. * * @param value the possible collection-like object, not null * @param parent the parent iterator, not null * @return the iterator, null if not a collection-like type */ public SerIterator createChild(Object value, SerIterator parent) { var declaredType = parent.valueType(); var childGenericTypes = parent.valueTypeTypes(); if (value instanceof Collection collection) { if (childGenericTypes.size() == 1) { return collection(collection, declaredType, childGenericTypes.getFirst(), EMPTY_VALUE_TYPES); } return collection(collection, Object.class, Object.class, EMPTY_VALUE_TYPES); } if (value instanceof Map map) { if (childGenericTypes.size() == 2) { return map(map, declaredType, childGenericTypes.getFirst(), childGenericTypes.get(1), EMPTY_VALUE_TYPES); } return map(map, Object.class, Object.class, Object.class, EMPTY_VALUE_TYPES); } if (value.getClass().isArray() && !value.getClass().getComponentType().isPrimitive()) { var array = (Object[]) value; return array(array, Object.class, value.getClass().getComponentType()); } return null; } /** * Defaults input class to Object class. * * @param type the type, may be null * @return the type, not null */ protected Class defaultToObjectClass(Class type) { return (type != null ? type : Object.class); } //----------------------------------------------------------------------- /** * Creates an iterator wrapper for a meta-type description. * * @param metaTypeDescription the description of the collection type, not null * @param settings the settings object, not null * @param knownTypes the known types map, null if not using known type shortening * @return the iterable, null if not a collection-like type */ public SerIterable createIterable(String metaTypeDescription, JodaBeanSer settings, Map> knownTypes) { if (metaTypeDescription.equals("Set")) { return set(Object.class, EMPTY_VALUE_TYPES); } if (metaTypeDescription.equals("List") || metaTypeDescription.equals("Collection")) { return list(Object.class, EMPTY_VALUE_TYPES); } if (metaTypeDescription.equals("Map")) { return map(Object.class, Object.class, EMPTY_VALUE_TYPES); } if (metaTypeDescription.endsWith("[][][]")) { throw new IllegalArgumentException("Three-dimensional arrays cannot be parsed"); } if (metaTypeDescription.endsWith("[][]")) { var type = META_TYPE_MAP.get(metaTypeDescription); if (type != null) { return array(type); } var clsStr = metaTypeDescription.substring(0, metaTypeDescription.length() - 4); try { var cls = SerTypeMapper.decodeType(clsStr, settings, null, knownTypes); var compound = "[L" + cls.getName() + ";"; return array(Class.forName(compound)); // needs to be Class.forName } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } } if (metaTypeDescription.endsWith("[]")) { var type = META_TYPE_MAP.get(metaTypeDescription); if (type == null) { var clsStr = metaTypeDescription.substring(0, metaTypeDescription.length() - 2); try { type = SerTypeMapper.decodeType(clsStr, settings, null, knownTypes); } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } } return array(type); } return null; } /** * Creates an iterator wrapper for a child where there are second level generic parameters. * * @param iterable the parent iterable, not null * @return the iterable, null if not a collection-like type */ public SerIterable createIterable(SerIterable iterable) { var valueTypeTypes = iterable.valueTypeTypes(); if (!valueTypeTypes.isEmpty()) { var valueType = iterable.valueType(); if (NavigableSet.class.isAssignableFrom(valueType)) { return navigableSet(valueTypeTypes.get(0), EMPTY_VALUE_TYPES); } if (SortedSet.class.isAssignableFrom(valueType)) { return sortedSet(valueTypeTypes.get(0), EMPTY_VALUE_TYPES); } if (Set.class.isAssignableFrom(valueType)) { return set(valueTypeTypes.get(0), EMPTY_VALUE_TYPES); } if (Collection.class.isAssignableFrom(valueType)) { // includes List return list(valueTypeTypes.get(0), EMPTY_VALUE_TYPES); } if (NavigableMap.class.isAssignableFrom(valueType)) { if (valueTypeTypes.size() == 2) { return navigableMap(valueTypeTypes.get(0), valueTypeTypes.get(1), EMPTY_VALUE_TYPES); } return navigableMap(Object.class, Object.class, EMPTY_VALUE_TYPES); } if (SortedMap.class.isAssignableFrom(valueType)) { if (valueTypeTypes.size() == 2) { return sortedMap(valueTypeTypes.get(0), valueTypeTypes.get(1), EMPTY_VALUE_TYPES); } return sortedMap(Object.class, Object.class, EMPTY_VALUE_TYPES); } if (Map.class.isAssignableFrom(valueType)) { if (valueTypeTypes.size() == 2) { return map(valueTypeTypes.get(0), valueTypeTypes.get(1), EMPTY_VALUE_TYPES); } return map(Object.class, Object.class, EMPTY_VALUE_TYPES); } if (valueType.isArray()) { return array(valueType.getComponentType()); } } return null; } /** * Creates an iterator wrapper for a meta-property value. * * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @param allowPrimitiveArrays whether to allow primitive arrays * @return the iterable, null if not a collection-like type */ public SerIterable createIterable(MetaProperty prop, Class beanClass, boolean allowPrimitiveArrays) { if (allowPrimitiveArrays && prop.propertyType().isArray() && prop.propertyType().getComponentType().isPrimitive() && prop.propertyType().getComponentType() != byte.class) { return arrayPrimitive(prop.propertyType().getComponentType()); } return createIterable(prop, beanClass); } /** * Creates an iterator wrapper for a meta-property value. * * @param prop the meta-property defining the value, not null * @param beanClass the class of the bean, not the meta-property, for better generics, not null * @return the iterable, null if not a collection-like type */ public SerIterable createIterable(MetaProperty prop, Class beanClass) { var propType = prop.propertyType(); if (NavigableSet.class.isAssignableFrom(propType)) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return navigableSet(valueType, valueTypeTypes); } if (SortedSet.class.isAssignableFrom(prop.propertyType())) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return sortedSet(valueType, valueTypeTypes); } if (Set.class.isAssignableFrom(prop.propertyType())) { var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return set(valueType, valueTypeTypes); } if (Collection.class.isAssignableFrom(prop.propertyType())) { // includes List var valueType = JodaBeanUtils.collectionType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.collectionTypeTypes(prop, beanClass); return list(valueType, valueTypeTypes); } if (NavigableMap.class.isAssignableFrom(prop.propertyType())) { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return navigableMap(keyType, valueType, valueTypeTypes); } if (SortedMap.class.isAssignableFrom(prop.propertyType())) { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return sortedMap(keyType, valueType, valueTypeTypes); } if (Map.class.isAssignableFrom(prop.propertyType())) { var keyType = JodaBeanUtils.mapKeyType(prop, beanClass); var valueType = JodaBeanUtils.mapValueType(prop, beanClass); var valueTypeTypes = JodaBeanUtils.mapValueTypeTypes(prop, beanClass); return map(keyType, valueType, valueTypeTypes); } if (prop.propertyType().isArray() && !prop.propertyType().getComponentType().isPrimitive()) { return array(prop.propertyType().getComponentType()); } return null; } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for {@code List}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable list(Class valueType, List> valueTypeTypes) { List coll = new ArrayList<>(); return new SerIterable() { @Override public SerIterator iterator() { return collection(coll, Object.class, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } for (var i = 0; i < count; i++) { coll.add(value); } } @Override public Object build() { return coll; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterable wrapper for {@code Set}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable set(Class valueType, List> valueTypeTypes) { Set coll = new HashSet<>(); return set(valueType, valueTypeTypes, coll); } /** * Gets an iterable wrapper for {@code SortedSet}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable sortedSet(Class valueType, List> valueTypeTypes) { SortedSet coll = new TreeSet<>(); return set(valueType, valueTypeTypes, coll); } /** * Gets an iterable wrapper for {@code NavigableSet}. * * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable navigableSet(Class valueType, List> valueTypeTypes) { NavigableSet coll = new TreeSet<>(); return set(valueType, valueTypeTypes, coll); } private static SerIterable set(Class valueType, List> valueTypeTypes, Set coll) { return new SerIterable() { @Override public SerIterator iterator() { return collection(coll, Object.class, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } for (var i = 0; i < count; i++) { coll.add(value); } } @Override public Object build() { return coll; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterator wrapper for {@code Collection}. * * @param coll the collection, not null * @param declaredType the declared type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator collection( Collection coll, Class declaredType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = coll.iterator(); private Object current; @Override public String metaTypeName() { if (coll instanceof Set) { return "Set"; } if (coll instanceof List) { return "List"; } return "Collection"; } @Override public boolean metaTypeRequired() { if (coll instanceof Set) { return !Set.class.isAssignableFrom(declaredType); } if (coll instanceof List) { return !List.class.isAssignableFrom(declaredType); } return !Collection.class.isAssignableFrom(declaredType); } @Override public int size() { return coll.size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = it.next(); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } @Override public Object value() { return current; } }; } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for {@code Map}. * * @param keyType the value type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable map(Class keyType, Class valueType, List> valueTypeTypes) { Map map = new HashMap<>(); return map(keyType, valueType, valueTypeTypes, map); } /** * Gets an iterable wrapper for {@code SortedMap}. * * @param keyType the value type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable sortedMap(Class keyType, Class valueType, List> valueTypeTypes) { SortedMap map = new TreeMap<>(); return map(keyType, valueType, valueTypeTypes, map); } /** * Gets an iterable wrapper for {@code NavigableMap}. * * @param keyType the value type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterable, not null */ public static SerIterable navigableMap(Class keyType, Class valueType, List> valueTypeTypes) { NavigableMap map = new TreeMap<>(); return map(keyType, valueType, valueTypeTypes, map); } static SerIterable map(Class keyType, Class valueType, List> valueTypeTypes, Map map) { return new SerIterable() { @Override public SerIterator iterator() { return map(map, Object.class, keyType, valueType, valueTypeTypes); } @Override public void add(Object key, Object column, Object value, int count) { if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } map.put(key, value); } @Override public Object build() { return map; } @Override public SerCategory category() { return SerCategory.MAP; } @Override public Class keyType() { return keyType; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } }; } /** * Gets an iterator wrapper for {@code Map}. * * @param map the collection, not null * @param declaredType the declared type, not null * @param keyType the value type, not null * @param valueType the value type, not null * @param valueTypeTypes the generic parameters of the value type * @return the iterator, not null */ @SuppressWarnings("rawtypes") public static SerIterator map( Map map, Class declaredType, Class keyType, Class valueType, List> valueTypeTypes) { return new SerIterator() { private final Iterator it = map.entrySet().iterator(); private Entry current; @Override public String metaTypeName() { return "Map"; } @Override public boolean metaTypeRequired() { return !Map.class.isAssignableFrom(declaredType); } @Override public SerCategory category() { return SerCategory.MAP; } @Override public int size() { return map.size(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public void next() { current = (Entry) it.next(); } @Override public Class keyType() { return keyType; } @Override public Object key() { return current.getKey(); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return valueTypeTypes; } @Override public Object value() { return current.getValue(); } }; } //----------------------------------------------------------------------- /** * Gets an iterable wrapper for an object array. * * @param valueType the value type, not null * @return the iterable, not null */ public static SerIterable array(Class valueType) { if (valueType.isPrimitive()) { return arrayPrimitive(valueType); } List list = new ArrayList<>(); return new SerIterable() { @Override public SerIterator iterator() { return array(build(), Object.class, valueType); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } for (var i = 0; i < count; i++) { list.add(value); } } @Override public Object[] build() { var array = (Object[]) Array.newInstance(valueType, list.size()); return list.toArray(array); } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return EMPTY_VALUE_TYPES; } }; } /** * Gets an iterable wrapper for a primitive array. * * @param valueType the value type, not null * @return the iterable, not null */ static SerIterable arrayPrimitive(Class valueType) { List list = new ArrayList<>(); return new SerIterable() { @Override public SerIterator iterator() { return arrayPrimitive(build(), Object.class, valueType); } @Override public void add(Object key, Object column, Object value, int count) { if (key != null) { throw new IllegalArgumentException("Unexpected key"); } if (count != 1) { throw new IllegalArgumentException("Unexpected count"); } for (var i = 0; i < count; i++) { list.add(value); } } @Override public Object build() { var array = Array.newInstance(valueType, list.size()); for (var i = 0; i < list.size(); i++) { Array.set(array, i, list.get(i)); } return array; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return EMPTY_VALUE_TYPES; } }; } /** * Gets an iterator wrapper for an object array. * * @param array the array, not null * @param declaredType the declared type, not null * @param valueType the value type, not null * @return the iterator, not null */ public static SerIterator array(Object[] array, Class declaredType, Class valueType) { return new SerIterator() { private int index = -1; @Override public String metaTypeName() { return metaTypeNameBase(valueType); } private String metaTypeNameBase(Class arrayType) { if (arrayType.isArray()) { return metaTypeNameBase(arrayType.getComponentType()) + "[]"; } if (arrayType == Object.class) { return "Object[]"; } if (arrayType == String.class) { return "String[]"; } return arrayType.getName() + "[]"; } @Override public boolean metaTypeRequired() { if (valueType == Object.class) { return !Object[].class.isAssignableFrom(declaredType); } if (valueType == String.class) { return !String[].class.isAssignableFrom(declaredType); } return true; } @Override public int size() { return array.length; } @Override public boolean hasNext() { return (index + 1) < array.length; } @Override public void next() { index++; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return Collections.emptyList(); } @Override public Object value() { return array[index]; } }; } /** * Gets an iterator wrapper for a primitive array. * * @param array the array, not null * @param declaredType the declared type, not null * @param valueType the value type, not null * @return the iterator, not null */ static SerIterator arrayPrimitive(Object array, Class declaredType, Class valueType) { var arrayLength = Array.getLength(array); return new SerIterator() { private int index = -1; @Override public String metaTypeName() { return metaTypeNameBase(valueType); } private String metaTypeNameBase(Class arrayType) { if (arrayType.isArray()) { return metaTypeNameBase(arrayType.getComponentType()) + "[]"; } if (arrayType == Object.class) { return "Object[]"; } if (arrayType == String.class) { return "String[]"; } return arrayType.getName() + "[]"; } @Override public boolean metaTypeRequired() { if (valueType == Object.class) { return !Object[].class.isAssignableFrom(declaredType); } if (valueType == String.class) { return !String[].class.isAssignableFrom(declaredType); } return true; } @Override public int size() { return arrayLength; } @Override public boolean hasNext() { return (index + 1) < arrayLength; } @Override public void next() { index++; } @Override public Class valueType() { return valueType; } @Override public List> valueTypeTypes() { return Collections.emptyList(); } @Override public Object value() { return Array.get(array, index); } }; } } ================================================ FILE: src/main/java/org/joda/beans/ser/SerOptional.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.Optional; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.OptionalLong; import java.util.function.BiFunction; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; /** * Assists with serialization and deserialization of optional properties. */ public class SerOptional { /** Guava Optional type. */ private static final Class GUAVA_OPTIONAL_CLASS; /** Extractor for Guava Optional. */ private static final Function GUAVA_EXTRACT; /** Wrapper for Guava Optional. */ private static final BiFunction, Object, Object> GUAVA_WRAPPER; static { Class optionalType; Function extract; BiFunction, Object, Object> wrapper; try { optionalType = GuavaSerOptional.OPTIONAL_TYPE; extract = GuavaSerOptional::extractValue; wrapper = GuavaSerOptional::wrapValue; } catch (RuntimeException | LinkageError ex) { optionalType = Optional.class; extract = Function.identity(); wrapper = (cls, value) -> value; } GUAVA_OPTIONAL_CLASS = optionalType; GUAVA_EXTRACT = extract; GUAVA_WRAPPER = wrapper; } /** * Extracts the value of the property from a bean, unwrapping any optional. * * @param metaProp the property to query, not null * @param bean the bean to query, not null * @return the value of the property, with any optional wrapper removed */ public static Object extractValue(MetaProperty metaProp, Bean bean) { var value = metaProp.get(bean); return switch (value) { case null -> null; case Optional opt -> opt.orElse(null); case OptionalLong opt -> opt.isPresent() ? opt.getAsLong() : null; case OptionalInt opt -> opt.isPresent() ? opt.getAsInt() : null; case OptionalDouble opt -> opt.isPresent() ? opt.getAsDouble() : null; default -> GUAVA_EXTRACT.apply(value); }; } /** * Extracts the type the optional is wrapping. * * @param metaProp the property to query, not null * @param beanType the type of the bean, not null * @return the type of the property with any optional wrapper removed */ public static Class extractType(MetaProperty metaProp, Class beanType) { var propType = metaProp.propertyType(); if (propType == Optional.class || propType == OptionalLong.class || propType == OptionalInt.class || propType == OptionalDouble.class || propType == GUAVA_OPTIONAL_CLASS) { return extractType(metaProp, beanType, propType); } return propType; } // broken out for hotspot private static Class extractType(MetaProperty metaProp, Class beanType, Class type) { try { var genericType = JodaBeanUtils.extractTypeClass(metaProp, beanType, 1, 0); return (genericType != null ? genericType : type); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * Wraps the value of a property if it is an optional. * * @param metaProp the property to query, not null * @param beanType the type of the bean, not null * @param value the value to wrap, may be null * @return the value of the property, with any optional wrapper added */ public static Object wrapValue(MetaProperty metaProp, Class beanType, Object value) { var propType = metaProp.propertyType(); if (propType == Optional.class) { return Optional.ofNullable(value); } else if (propType == OptionalLong.class) { return value == null ? OptionalLong.empty() : OptionalLong.of((Long) value); } else if (propType == OptionalInt.class) { return value == null ? OptionalInt.empty() : OptionalInt.of((Integer) value); } else if (propType == OptionalDouble.class) { return value == null ? OptionalDouble.empty() : OptionalDouble.of((Double) value); } else { return GUAVA_WRAPPER.apply(propType, value); } } //------------------------------------------------------------------------- // a separate class so that it can fail to load if Guava is missing private static final class GuavaSerOptional { public static final Class OPTIONAL_TYPE = com.google.common.base.Optional.class; private static Object extractValue(Object value) { return value instanceof com.google.common.base.Optional opt ? opt.orNull() : value; } public static Object wrapValue(Class propType, Object value) { if (propType == OPTIONAL_TYPE) { return com.google.common.base.Optional.fromNullable(value); } return value; } } } ================================================ FILE: src/main/java/org/joda/beans/ser/SerTypeMapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.io.File; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.util.Collections; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import org.joda.convert.RenameHandler; /** * Type mapper for Joda-Bean serialization, used by serialization implementations. */ public final class SerTypeMapper { /** * Known simple classes. */ private static final Map, String> BASIC_TYPES; /** * Known simple classes. */ private static final Map> BASIC_TYPES_REVERSED; static { Map, String> map = new HashMap<>(); map.put(String.class, "String"); map.put(Long.class, "Long"); map.put(Integer.class, "Integer"); map.put(Short.class, "Short"); map.put(Byte.class, "Byte"); map.put(Character.class, "Character"); map.put(Boolean.class, "Boolean"); map.put(Double.class, "Double"); map.put(Float.class, "Float"); map.put(BigInteger.class, "BigInteger"); map.put(BigDecimal.class, "BigDecimal"); map.put(Locale.class, "Locale"); map.put(Class.class, "Class"); map.put(UUID.class, "UUID"); map.put(URI.class, "URI"); map.put(File.class, "File"); // selection of types are the most common types suitable for reduction // and suitable for simple interpretation on non-Java systems Map> reversed = new HashMap<>(); for (Entry, String> entry : map.entrySet()) { reversed.put(entry.getValue(), entry.getKey()); } BASIC_TYPES = Collections.unmodifiableMap(map); BASIC_TYPES_REVERSED = Collections.unmodifiableMap(reversed); } /** * Creates an instance. */ private SerTypeMapper() { } //----------------------------------------------------------------------- /** * Encodes a basic class. *

* This handles known simple types, like String, Integer or File, and prefixing. * It also allows a map of message specific shorter forms. * * @param cls the class to encode, not null * @param settings the settings object, not null * @param basePackage the base package to use with trailing dot, null if none * @param knownTypes the known types map, null if not using known type shortening * @return the class object, null if not a basic type */ public static String encodeType(Class cls, JodaBeanSer settings, String basePackage, Map, String> knownTypes) { // basic type var result = BASIC_TYPES.get(cls); if (result != null) { return result; } // handle enum subclasses Class supr1 = cls.getSuperclass(); if (supr1 != null) { Class supr2 = supr1.getSuperclass(); if (supr2 == Enum.class) { cls = supr1; } } // calculate if (settings.isShortTypes()) { if (knownTypes != null) { result = knownTypes.get(cls); if (result != null) { return result; } } result = cls.getName(); if (basePackage != null && result.startsWith(basePackage) && Character.isUpperCase(result.charAt(basePackage.length())) && !BASIC_TYPES_REVERSED.containsKey(result.substring(basePackage.length()))) { // use short format result = result.substring(basePackage.length()); if (knownTypes != null) { knownTypes.put(cls, result); } } else { // use long format, short next time if possible if (knownTypes != null) { var simpleName = cls.getSimpleName(); if (Character.isUpperCase(simpleName.charAt(0)) && !BASIC_TYPES_REVERSED.containsKey(simpleName) && !knownTypes.containsValue(simpleName)) { knownTypes.put(cls, simpleName); } else { knownTypes.put(cls, result); } } } } else { result = cls.getName(); } return result; } /** * Decodes a class, throwing an exception if not found. *

* This uses the context class loader. * This handles known simple types, like String, Integer or File, and prefixing. * It also allows a map of message specific shorter forms. * * @param className the class name, not null * @param settings the settings object, not null * @param basePackage the base package to use with trailing dot, null if none * @param knownTypes the known types map, null if not using known type shortening * @return the class object, not null * @throws ClassNotFoundException if not found */ public static Class decodeType( String className, JodaBeanSer settings, String basePackage, Map> knownTypes) throws ClassNotFoundException { return decodeType0(className, settings, basePackage, knownTypes, null); } /** * Decodes a class, returning a default if not found. *

* This uses the context class loader. * This handles known simple types, like String, Integer or File, and prefixing. * It also allows a map of message specific shorter forms. * * @param className the class name, not null * @param settings the settings object, not null * @param basePackage the base package to use with trailing dot, null if none * @param knownTypes the known types map, null if not using known type shortening * @param defaultType the type to use as a default if the type cannot be found * @return the class object, not null * @throws ClassNotFoundException if an error occurs */ public static Class decodeType( String className, JodaBeanSer settings, String basePackage, Map> knownTypes, Class defaultType) throws ClassNotFoundException { return decodeType0(className, settings, basePackage, knownTypes, defaultType); } // internal type decode private static Class decodeType0( String className, JodaBeanSer settings, String basePackage, Map> knownTypes, Class defaultType) throws ClassNotFoundException { // basic type Class result = BASIC_TYPES_REVERSED.get(className); if (result != null) { return result; } // check cache if (knownTypes != null) { result = knownTypes.get(className); if (result != null) { return result; } } // calculate var fullName = className; var expanded = false; if (basePackage != null && !className.isEmpty() && Character.isUpperCase(className.charAt(0))) { fullName = basePackage + className; expanded = true; } try { result = RenameHandler.INSTANCE.lookupType(fullName); if (knownTypes != null) { // cache full name knownTypes.put(fullName, result); if (expanded) { // cache short name knownTypes.put(className, result); } else { // derive and cache short name var simpleName = result.getSimpleName(); // handle renames if (!fullName.equals(result.getName()) && RenameHandler.INSTANCE.getTypeRenames().containsKey(fullName) && result.getEnclosingClass() == null) { simpleName = fullName.substring(fullName.lastIndexOf(".") + 1); } if (Character.isUpperCase(simpleName.charAt(0)) && !BASIC_TYPES_REVERSED.containsKey(simpleName) && !knownTypes.containsKey(simpleName)) { knownTypes.put(simpleName, result); } } } return result; } catch (ClassNotFoundException ex) { // handle pathological case of package name starting with upper case if (!fullName.equals(className)) { try { result = RenameHandler.INSTANCE.lookupType(className); if (knownTypes != null) { knownTypes.put(className, result); } return result; } catch (ClassNotFoundException ignored) { } } if (defaultType == null) { throw ex; } return defaultType; } } //----------------------------------------------------------------------- @Override public String toString() { return getClass().getSimpleName(); } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/AbstractBinReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerIterable; import org.joda.beans.ser.SerIteratorFactory; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; /** * Provides the ability for a Joda-Bean to read from both the standard and referencing binary formats. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ abstract class AbstractBinReader extends MsgPack { /** * Settings. */ final JodaBeanSer settings; // CSIGNORE /** * The reader. */ final DataInputStream input; // CSIGNORE /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map> knownTypes = new HashMap<>(); //----------------------------------------------------------------------- // creates an instance AbstractBinReader(JodaBeanSer settings, DataInputStream input) { this.settings = settings; this.input = input; } //----------------------------------------------------------------------- // reads the input stream where the array and version bytes have been read already T read(Class rootType) { try { try { return parseRemaining(rootType); } finally { input.close(); } } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } T parseRemaining(Class declaredType) throws Exception { // the array and version has already been read var parsed = parseObject(declaredType, null, null, null, true); return declaredType.cast(parsed); } Object parseBean(int propertyCount, Class beanType) { var propName = ""; try { var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); var builder = deser.createBuilder(beanType, metaBean); for (var i = 0; i < propertyCount; i++) { // property name propName = acceptPropertyName(); var metaProp = deser.findMetaProperty(beanType, metaBean, propName); if (metaProp == null || metaProp.style().isDerived()) { MsgPackInput.skipObject(input); } else { var value = parseObject(SerOptional.extractType(metaProp, beanType), metaProp, beanType, null, false); deser.setValue(builder, metaProp, SerOptional.wrapValue(metaProp, beanType, value)); } } propName = ""; return deser.build(beanType, builder); } catch (Exception ex) { throw new RuntimeException("Error parsing bean: " + beanType.getName() + "::" + propName + ", " + ex.getMessage(), ex); } } String acceptPropertyName() throws IOException { var typeByte = input.readByte(); return acceptString(typeByte); } //------------------------------------------------------------------------- // parses an object, determining how to parse based on the input data Object parseObject(Class declaredType, MetaProperty metaProp, Class beanType, SerIterable parentIterable, boolean rootType) throws Exception { var typeByte = input.readByte(); // parse metadata if (isMap(typeByte)) { input.mark(8); var mapSize = acceptMap(typeByte); if (mapSize > 0) { int typeByteTemp = input.readByte(); if (typeByteTemp == EXT_8) { var size = input.readUnsignedByte(); typeByteTemp = input.readByte(); if (typeByteTemp == JODA_TYPE_BEAN) { var typeStr = acceptStringBytes(size); var effectiveType = SerTypeMapper.decodeType(typeStr, settings, basePackage, knownTypes); return parseObjectAsBean(declaredType, rootType, effectiveType, mapSize); } else if (typeByteTemp == JODA_TYPE_DATA) { if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } var typeStr = acceptStringBytes(size); var effectiveType = settings.getDeserializers().decodeType( typeStr, settings, basePackage, knownTypes, declaredType); if (!declaredType.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Specified type is incompatible with declared type: " + declaredType.getName() + " and " + effectiveType.getName()); } return parseObjectFromInput(input.readByte(), effectiveType, metaProp, beanType, parentIterable); } else if (typeByteTemp == JODA_TYPE_META) { return parseObjectAsCollectionWithMeta(mapSize, size); } } } input.reset(); } // parse based on type return parseObjectFromInput(typeByte, declaredType, metaProp, beanType, parentIterable); } // a bean with an explicit type private Object parseObjectAsBean(Class declaredType, boolean rootType, Class effectiveType, int mapSize) throws Exception { if (rootType) { if (!Bean.class.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Root type is not a Joda-Bean: " + effectiveType.getName()); } basePackage = effectiveType.getPackage().getName() + "."; } if (!declaredType.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Specified type is incompatible with declared type: " + declaredType.getName() + " and " + effectiveType.getName()); } if (input.readByte() != NIL) { throw new IllegalArgumentException("Invalid binary data: Expected null after bean type"); } return parseBean(mapSize - 1, effectiveType); } // a collection with a meta annotation private Object parseObjectAsCollectionWithMeta(int mapSize, int strSize) throws Exception { if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } var metaType = acceptStringBytes(strSize); var typeByte = input.readByte(); if (isMap(typeByte) || isArray(typeByte)) { var childIterable = settings.getIteratorFactory().createIterable(metaType, settings, knownTypes); if (childIterable == null) { throw new IllegalArgumentException("Invalid binary data: Invalid metaType: " + metaType); } return parseIterable(typeByte, childIterable); } else { throw new IllegalArgumentException("Invalid binary data: MetaType was not followed by a collection: " + metaType); } } private Object parseObjectFromInput( int typeByte, Class effectiveType, MetaProperty metaProp, Class beanType, SerIterable parentIterable) throws Exception { if (typeByte == NIL) { return null; } else if (Bean.class.isAssignableFrom(effectiveType)) { if (isMap(typeByte)) { var mapSize = acceptMap(typeByte); return parseBean(mapSize, effectiveType); } else { return parseSimple(typeByte, effectiveType); } } else if (isMap(typeByte) || isArray(typeByte)) { SerIterable childIterable = null; if (metaProp != null) { childIterable = settings.getIteratorFactory().createIterable(metaProp, beanType); } else if (parentIterable != null) { childIterable = settings.getIteratorFactory().createIterable(parentIterable); } if (childIterable == null) { // handle array types sent without a metatype if (effectiveType.isArray()) { childIterable = SerIteratorFactory.array(effectiveType.getComponentType()); } else { throw new IllegalArgumentException("Invalid binary data: Unable to create collection type"); } } return parseIterable(typeByte, childIterable); } else { return parseSimple(typeByte, effectiveType); } } Object parseIterable(int typeByte, SerIterable iterable) throws Exception { return switch (iterable.category()) { case COLLECTION -> parseIterableArray(typeByte, iterable); case COUNTED -> parseIterableCounted(typeByte, iterable); case MAP -> parseIterableMap(typeByte, iterable); case TABLE -> parseIterableTable(typeByte, iterable); case GRID -> parseIterableGrid(typeByte, iterable); }; } Object parseIterableMap(int typeByte, SerIterable iterable) throws Exception { var size = acceptMap(typeByte); for (var i = 0; i < size; i++) { var key = parseObject(iterable.keyType(), null, null, null, false); var value = parseObject(iterable.valueType(), null, null, iterable, false); iterable.add(key, null, value, 1); } return iterable.build(); } Object parseIterableTable(int typeByte, SerIterable iterable) throws Exception { var size = acceptArray(typeByte); for (var i = 0; i < size; i++) { if (acceptArray(input.readByte()) != 3) { throw new IllegalArgumentException("Table must have cell array size 3"); } var key = parseObject(iterable.keyType(), null, null, null, false); var column = parseObject(iterable.columnType(), null, null, null, false); var value = parseObject(iterable.valueType(), null, null, iterable, false); iterable.add(key, column, value, 1); } return iterable.build(); } Object parseIterableGrid(int typeByte, SerIterable iterable) throws Exception { var size = acceptArray(typeByte); var rows = acceptInteger(input.readByte()); var columns = acceptInteger(input.readByte()); iterable.dimensions(new int[] {rows, columns}); if ((rows * columns) != (size - 2)) { // sparse for (var i = 0; i < (size - 2); i++) { if (acceptArray(input.readByte()) != 3) { throw new IllegalArgumentException("Grid must have cell array size 3"); } var row = acceptInteger(input.readByte()); var column = acceptInteger(input.readByte()); var value = parseObject(iterable.valueType(), null, null, iterable, false); iterable.add(row, column, value, 1); } } else { // dense for (var row = 0; row < rows; row++) { for (var column = 0; column < columns; column++) { var value = parseObject(iterable.valueType(), null, null, iterable, false); iterable.add(row, column, value, 1); } } } return iterable.build(); } Object parseIterableCounted(int typeByte, SerIterable iterable) throws Exception { var size = acceptMap(typeByte); for (var i = 0; i < size; i++) { var value = parseObject(iterable.valueType(), null, null, iterable, false); var count = acceptInteger(input.readByte()); iterable.add(null, null, value, count); } return iterable.build(); } Object parseIterableArray(int typeByte, SerIterable iterable) throws Exception { var size = acceptArray(typeByte); for (var i = 0; i < size; i++) { iterable.add(null, null, parseObject(iterable.valueType(), null, null, iterable, false), 1); } return iterable.build(); } //------------------------------------------------------------------------- Object parseSimple(int typeByte, Class type) throws Exception { if (isString(typeByte)) { var text = acceptString(typeByte); if (type == String.class || type.isAssignableFrom(String.class)) { return text; } return settings.getConverter().convertFromString(type, text); } if (isIntegral(typeByte)) { // ordered from common to less-common var value = acceptLong(typeByte); if (type == Long.class || type == long.class) { return Long.valueOf(value); } else if (type == Integer.class || type == int.class) { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected int, but was " + value); } return Integer.valueOf((int) value); } else if (type == Double.class || type == double.class) { // handle case where property type has changed from integral to double return Double.valueOf(value); } else if (type == Short.class || type == short.class) { if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected byte, but was " + value); } return Short.valueOf((short) value); } else if (type == Byte.class || type == byte.class) { if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected byte, but was " + value); } return Byte.valueOf((byte) value); } else if (type == Float.class || type == float.class) { // handle case where property type has changed from integral to float return Float.valueOf(value); } else { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { return Long.valueOf(value); } return Integer.valueOf((int) value); } } return switch (typeByte) { case TRUE -> Boolean.TRUE; case FALSE -> Boolean.FALSE; case FLOAT_32 -> Float.valueOf(input.readFloat()); case FLOAT_64 -> Double.valueOf(input.readDouble()); case BIN_8, BIN_16, BIN_32 -> acceptBinary(typeByte); default -> throw invalidBinaryData(type.getName(), typeByte); }; } //----------------------------------------------------------------------- int acceptMap(int typeByte) throws IOException { if (typeByte >= MIN_FIX_MAP && typeByte <= MAX_FIX_MAP) { return (typeByte - MIN_FIX_MAP); } else if (typeByte == MAP_16) { return input.readUnsignedShort(); } else if (typeByte == MAP_32) { return readPositiveInt("Invalid binary data: Map too large"); } else { throw invalidBinaryData("map", typeByte); } } int acceptArray(int typeByte) throws IOException { if (typeByte >= MIN_FIX_ARRAY && typeByte <= MAX_FIX_ARRAY) { return typeByte - MIN_FIX_ARRAY; } else if (typeByte == ARRAY_16) { return input.readUnsignedShort(); } else if (typeByte == ARRAY_32) { return readPositiveInt("Invalid binary data: Array too large"); } else { throw invalidBinaryData("array", typeByte); } } String acceptString(int typeByte) throws IOException { int size; if (typeByte >= MIN_FIX_STR && typeByte <= MAX_FIX_STR) { size = typeByte - MIN_FIX_STR; } else if (typeByte == STR_8) { size = input.readUnsignedByte(); } else if (typeByte == STR_16) { size = input.readUnsignedShort(); } else if (typeByte == STR_32) { size = readPositiveInt("Invalid binary data: String too large"); } else { throw invalidBinaryData("string", typeByte); } return acceptStringBytes(size); } String acceptStringBytes(int size) throws IOException { var bytes = new byte[size]; input.readFully(bytes); // inline common ASCII case for much better performance var chars = new char[size]; for (var i = 0; i < size; i++) { var b = bytes[i]; if (b >= 0) { chars[i] = (char) b; } else { return new String(bytes, UTF_8); } } return new String(chars); } byte[] acceptBinary(int typeByte) throws IOException { int size = switch (typeByte) { case BIN_8 -> input.readUnsignedByte(); case BIN_16 -> input.readUnsignedShort(); case BIN_32 -> readPositiveInt("Invalid binary data: Binary too large"); default -> throw invalidBinaryData("binary", typeByte); }; var bytes = new byte[size]; input.readFully(bytes); return bytes; } int acceptInteger(int typeByte) throws IOException { if (typeByte >= MIN_FIX_INT && typeByte <= MAX_FIX_INT) { return typeByte; } return switch (typeByte) { case UINT_8 -> input.readUnsignedByte(); case UINT_16 -> input.readUnsignedShort(); case UINT_32 -> readPositiveInt("Invalid binary data: Expected int, but was large unsigned int"); case UINT_64 -> readUnsignedLongAsInt(); case SINT_8 -> input.readByte(); case SINT_16 -> input.readShort(); case SINT_32 -> input.readInt(); case SINT_64 -> readLongAsInt(); default -> throw invalidBinaryData("int", typeByte); }; } long acceptLong(int typeByte) throws IOException { if (typeByte >= MIN_FIX_INT && typeByte <= MAX_FIX_INT) { return typeByte; } return switch (typeByte) { case UINT_8 -> input.readUnsignedByte(); case UINT_16 -> input.readUnsignedShort(); case UINT_32 -> Integer.toUnsignedLong(input.readInt()); case UINT_64 -> readUnsignedLong(); case SINT_8 -> input.readByte(); case SINT_16 -> input.readShort(); case SINT_32 -> input.readInt(); case SINT_64 -> input.readLong(); default -> throw invalidBinaryData("long", typeByte); }; } private int readPositiveInt(String msg) throws IOException { var val = input.readInt(); if (val < 0) { throw new IllegalArgumentException(msg); } return val; } private long readUnsignedLong() throws IOException { var val = input.readLong(); if (val < 0) { throw new IllegalArgumentException("Invalid binary data: Expected long, but was large unsigned int"); } return val; } private int readUnsignedLongAsInt() throws IOException { var val = input.readLong(); if (val < 0 || val > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected int, but was large unsigned int"); } return (int) val; } private int readLongAsInt() throws IOException { var val = input.readLong(); if (val < Integer.MIN_VALUE || val > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected int, but was large signed int"); } return (int) val; } private IllegalArgumentException invalidBinaryData(String expected, int actualByte) { return new IllegalArgumentException( "Invalid binary data: Expected " + expected + ", but was: 0x" + toHex(actualByte)); } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/AbstractBinWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerIterator; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; /** * Provides the ability for a Joda-Bean to be written to both the standard and referencing binary formats. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ abstract class AbstractBinWriter { /** * The settings to use. */ final JodaBeanSer settings; // CSIGNORE /** * The output stream. */ final MsgPackOutput output; // CSIGNORE /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map, String> knownTypes = new HashMap<>(); // creates an instance AbstractBinWriter(JodaBeanSer settings, OutputStream output) { this.settings = settings; this.output = new MsgPackOutput(output); } //----------------------------------------------------------------------- void writeRootBean(Bean bean, boolean rootTypeFlag) throws IOException { writeBean(bean, bean.getClass(), rootTypeFlag ? RootType.ROOT_WITH_TYPE : RootType.ROOT_WITHOUT_TYPE); } void writeBean(Bean bean, Class declaredType, RootType rootTypeFlag) throws IOException { var count = bean.metaBean().metaPropertyCount(); var props = new MetaProperty[count]; var values = new Object[count]; var size = 0; for (var prop : bean.metaBean().metaPropertyIterable()) { if (settings.isSerialized(prop)) { var value = SerOptional.extractValue(prop, bean); if (value != null) { props[size] = prop; values[size++] = value; } } } if (rootTypeFlag == RootType.ROOT_WITH_TYPE || (rootTypeFlag == RootType.NOT_ROOT && bean.getClass() != declaredType)) { var type = SerTypeMapper.encodeType(bean.getClass(), settings, basePackage, knownTypes); if (rootTypeFlag == RootType.ROOT_WITH_TYPE) { basePackage = bean.getClass().getPackage().getName() + "."; } output.writeMapHeader(size + 1); output.writeExtensionString(MsgPack.JODA_TYPE_BEAN, type); output.writeNil(); } else { output.writeMapHeader(size); } for (var i = 0; i < size; i++) { MetaProperty prop = props[i]; var value = values[i]; output.writeString(prop.name()); var propType = SerOptional.extractType(prop, bean.getClass()); if (value instanceof Bean beanValue) { if (settings.getConverter().isConvertible(value.getClass())) { writeSimple(propType, value); } else { writeBean(beanValue, propType, RootType.NOT_ROOT); } } else { var itemIterator = settings.getIteratorFactory().create(value, prop, bean.getClass()); if (itemIterator != null) { writeElements(itemIterator); } else { writeSimple(propType, value); } } } } //----------------------------------------------------------------------- void writeMetaPropertyReference(String metaTypeName) throws IOException { output.writeExtensionString(MsgPack.JODA_TYPE_META, metaTypeName); } void writeElements(SerIterator itemIterator) throws IOException { if (itemIterator.metaTypeRequired()) { output.writeMapHeader(1); writeMetaPropertyReference(itemIterator.metaTypeName()); } switch (itemIterator.category()) { case COLLECTION -> writeArray(itemIterator); case COUNTED -> writeCounted(itemIterator); case MAP -> writeMap(itemIterator); case TABLE -> writeTable(itemIterator); case GRID -> writeGrid(itemIterator); } } void writeArray(SerIterator itemIterator) throws IOException { output.writeArrayHeader(itemIterator.size()); while (itemIterator.hasNext()) { itemIterator.next(); writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); } } void writeMap(SerIterator itemIterator) throws IOException { output.writeMapHeader(itemIterator.size()); while (itemIterator.hasNext()) { itemIterator.next(); writeObject(itemIterator.keyType(), itemIterator.key(), null); writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); } } void writeTable(SerIterator itemIterator) throws IOException { output.writeArrayHeader(itemIterator.size()); while (itemIterator.hasNext()) { itemIterator.next(); output.writeArrayHeader(3); writeObject(itemIterator.keyType(), itemIterator.key(), null); writeObject(itemIterator.columnType(), itemIterator.column(), null); writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); } } void writeGrid(SerIterator itemIterator) throws IOException { var rows = itemIterator.dimensionSize(0); var columns = itemIterator.dimensionSize(1); var totalSize = rows * columns; if (itemIterator.size() < (totalSize / 4)) { // sparse output.writeArrayHeader(itemIterator.size() + 2); output.writeInt(rows); output.writeInt(columns); while (itemIterator.hasNext()) { itemIterator.next(); output.writeArrayHeader(3); output.writeInt((Integer) itemIterator.key()); output.writeInt((Integer) itemIterator.column()); writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); } } else { // dense output.writeArrayHeader(totalSize + 2); output.writeInt(rows); output.writeInt(columns); for (var row = 0; row < rows; row++) { for (var column = 0; column < columns; column++) { writeObject(itemIterator.valueType(), itemIterator.value(row, column), itemIterator); } } } } void writeCounted(SerIterator itemIterator) throws IOException { output.writeMapHeader(itemIterator.size()); while (itemIterator.hasNext()) { itemIterator.next(); writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); output.writeInt(itemIterator.count()); } } void writeObject(Class declaredType, Object obj, SerIterator parentIterator) throws IOException { if (obj == null) { output.writeNil(); } else if (settings.getConverter().isConvertible(obj.getClass())) { writeSimple(declaredType, obj); } else if (obj instanceof Bean bean) { writeBean(bean, declaredType, RootType.NOT_ROOT); } else if (parentIterator != null) { var childIterator = settings.getIteratorFactory().createChild(obj, parentIterator); if (childIterator != null) { writeElements(childIterator); } else { writeSimple(declaredType, obj); } } else { writeSimple(declaredType, obj); } } //----------------------------------------------------------------------- void writeSimple(Class declaredType, Object value) throws IOException { // simple types have no need to write a type object switch (value) { case Integer val -> { output.writeInt(val); return; } case Double val -> { output.writeDouble(val); return; } case Float val -> { output.writeFloat(val); return; } case Boolean val -> { output.writeBoolean(val); return; } default -> { } } // handle no declared type and subclasses Class effectiveType = getAndSerializeEffectiveTypeIfRequired(value, declaredType); // long/short/byte only processed now to ensure that a distinction can be made between Integer and Long // (the method call above writes additional type information into the output stream) switch (value) { case Long val -> { output.writeLong(val); return; } case Short val -> { output.writeInt(val); return; } case Byte val -> { output.writeInt(val); return; } case byte[] val -> { output.writeBytes(val); return; } default -> { } } // write as a string try { writeObjectAsString(value, effectiveType); } catch (RuntimeException ex) { throw new IllegalArgumentException("Unable to convert type " + effectiveType.getName() + " declared as " + declaredType.getName(), ex); } } // called when serializing an object in {@link #writeSimple(Class, Object)}, to get the effective type of the // object and if necessary to serialize the class information // needs to handle no declared type and subclass instances Class getAndSerializeEffectiveTypeIfRequired(Object value, Class declaredType) throws IOException { var realType = value.getClass(); if (declaredType == Object.class) { if (realType != String.class) { var effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); output.writeMapHeader(1); var type = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); output.writeExtensionString(MsgPack.JODA_TYPE_DATA, type); return effectiveType; } else { return realType; } } if (!settings.getConverter().isConvertible(declaredType)) { var effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); output.writeMapHeader(1); var type = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); output.writeExtensionString(MsgPack.JODA_TYPE_DATA, type); return effectiveType; } return declaredType; } // writes a value as a string // called after discerning that the value is not a simple type void writeObjectAsString(Object value, Class effectiveType) throws IOException { var converted = settings.getConverter().convertToString(effectiveType, value); if (converted == null) { throw new IllegalArgumentException("Unable to write because converter returned a null string: " + value); } output.writeString(converted); } //----------------------------------------------------------------------- enum RootType { ROOT_WITH_TYPE, ROOT_WITHOUT_TYPE, NOT_ROOT, } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/BeanPack.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; /** * Constants used in MsgPack binary serialization. *

* This uses the v2.0 specification of MsgPack as of 2014-01-29. */ abstract class BeanPack { /** * UTF-8 encoding. */ static final Charset UTF_8 = StandardCharsets.UTF_8; /** * The smallest length of string that is cached. */ static final int MIN_LENGTH_STR_VALUE = 3; // fixed-size numbers /** * Maximum fixed int (7 bits). */ static final int MAX_FIX_INT = 0x7F; /** * Minimum fixed int (4 bits). */ static final int MIN_FIX_INT = 0xFFFFFFF0; // maps /** * Min fixed map - up to length 12. */ static final int MIN_FIX_MAP = 0xFFFFFF80; /** * Max fixed map. */ static final int MAX_FIX_MAP = 0xFFFFFF8C; /** * Map - followed by the size as an unsigned byte. */ static final int MAP_8 = 0xFFFFFF8D; /** * Map - followed by the size as an unsigned short. */ static final int MAP_16 = 0xFFFFFF8E; /** * Map - followed by the size as an unsigned long. */ static final int MAP_32 = 0xFFFFFF8F; // arrays /** * Min fixed array - up to length 12. */ static final int MIN_FIX_ARRAY = 0xFFFFFF90; // must be same as MsgPack /** * Max fixed array. */ static final int MAX_FIX_ARRAY = 0xFFFFFF9C; /** * Array - followed by the size as an unsigned byte. */ static final int ARRAY_8 = 0xFFFFFF9D; /** * Array - followed by the size as an unsigned short. */ static final int ARRAY_16 = 0xFFFFFF9E; /** * Array - followed by the size as an unsigned long. */ static final int ARRAY_32 = 0xFFFFFF9F; // strings /** * Min fixed string - up to length 40. */ static final int MIN_FIX_STR = 0xFFFFFFA0; /** * Max fixed string. */ static final int MAX_FIX_STR = 0xFFFFFFC8; /** * String - followed by the size as an unsigned byte. */ static final int STR_8 = 0xFFFFFFC9; /** * String - followed by the size as an unsigned short. */ static final int STR_16 = 0xFFFFFFCA; /** * String - followed by the size as an unsigned int. */ static final int STR_32 = 0xFFFFFFCB; // primitives /** * Null. */ static final int NULL = 0xFFFFFFCC; /** * False. */ static final int FALSE = 0xFFFFFFCD; /** * True. */ static final int TRUE = 0xFFFFFFCE; /** * Unused. */ static final int UNUSED = 0xFFFFFFCF; // numbers /** * Float - followed by 4 bytes. */ static final int FLOAT_32 = 0xFFFFFFD0; /** * Double in 1-byte int format - followed by 1 byte signed int */ static final int DOUBLE_INT_8 = 0xFFFFFFD1; /** * Double - followed by 8 bytes. */ static final int DOUBLE_64 = 0xFFFFFFD2; /** * Char (unsigned) - followed by 2 bytes. */ static final int CHAR_16 = 0xFFFFFFD3; /** * Byte (signed) - followed by 1 byte. */ static final int BYTE_8 = 0xFFFFFFD4; /** * Short (signed) - followed by 2 bytes. */ static final int SHORT_16 = 0xFFFFFFD5; /** * Int (signed) - followed by 2 bytes. */ static final int INT_16 = 0xFFFFFFD6; /** * Int (signed) - followed by 4 bytes. */ static final int INT_32 = 0xFFFFFFD7; /** * Long (signed) - followed by 1 byte. */ static final int LONG_8 = 0xFFFFFFD8; /** * Long (signed) - followed by 2 bytes. */ static final int LONG_16 = 0xFFFFFFD9; /** * Long (signed) - followed by 4 bytes. */ static final int LONG_32 = 0xFFFFFFDA; /** * Long (signed) - followed by 8 bytes. */ static final int LONG_64 = 0xFFFFFFDB; // date/time /** * LocalDate (2 bytes) - packed format from year 2000 to 2169 inclusive, * 11 bits for year-month from 2000, 5 bits for 1-based day-of-month. */ static final int DATE_PACKED = 0xFFFFFFDC; /** * LocalDate (5 bytes) - 27 bits for year-month, 5 bits for 1-based day-of-month. */ static final int DATE = 0xFFFFFFDD; /** * LocalTime (6 bytes) - 6 byte nano-of-day. */ static final int TIME = 0xFFFFFFDE; /** * Instant (12 bytes) - 8 for the seconds and 4 for the nanoseconds. */ static final int INSTANT = 0xFFFFFFDF; /** * Duration (12 bytes) - 8 for the seconds and 4 for the nanoseconds. */ static final int DURATION = 0xFFFFFFE0; // byte[]/double[] /** * byte[] - followed by the size as an unsigned short. */ static final int BIN_8 = 0xFFFFFFE1; /** * byte[] - followed by the size as an unsigned short. */ static final int BIN_16 = 0xFFFFFFE2; /** * byte[] - followed by the size as an unsigned int. */ static final int BIN_32 = 0xFFFFFFE3; /** * double[] - followed by the size as an unsigned byte. */ static final int DOUBLE_ARRAY_8 = 0xFFFFFFE4; /** * double[] - followed by the size as an unsigned short. */ static final int DOUBLE_ARRAY_16 = 0xFFFFFFE5; /** * double[] - followed by the size as an unsigned int. */ static final int DOUBLE_ARRAY_32 = 0xFFFFFFE6; // types and references /** * Type definition - followed by a 1 byte length, UTF-8 string and the actual value. */ static final int TYPE_DEFN_8 = 0xFFFFFFE7; /** * Type definition - followed by a 2 byte length, UTF-8 string and the actual value. */ static final int TYPE_DEFN_16 = 0xFFFFFFE8; /** * Reference to a type name - followed by a 1 byte int and the actual value. */ static final int TYPE_REF_8 = 0xFFFFFFE9; /** * Reference to a type name - followed by a 2 byte int and the actual value. */ static final int TYPE_REF_16 = 0xFFFFFFEA; /** * Bean with full definition - followed by a 1 byte int count of properties, then each property name, * then each property value, nulls replacing non-serialized entries. * Beans with 256 or more properties are not recorded as bean definitions. */ static final int BEAN_DEFN = 0xFFFFFFEB; /** * Value with full definition - followed by the value. */ static final int VALUE_DEFN = 0xFFFFFFEC; /** * Reference to a previous value - followed by a 1 byte int and the actual value. */ static final int VALUE_REF_8 = 0xFFFFFFED; /** * Reference to a previous value - followed by a 2 byte int and the actual value. */ static final int VALUE_REF_16 = 0xFFFFFFEE; /** * Reference to a previous value - followed by a 3 byte int and the actual value. */ static final int VALUE_REF_24 = 0xFFFFFFEF; //------------------------------------------------------------------------- /** * Set type code, followed by an array of values. */ static final int TYPE_CODE_LIST = -1; /** * Set type code, followed by an array of values. */ static final int TYPE_CODE_SET = -2; /** * Set type code, followed by an array of values. */ static final int TYPE_CODE_MAP = -3; /** * Optional type code, followed by a value, where a null value means empty. */ static final int TYPE_CODE_OPTIONAL = -4; /** * Multiset type code, followed by a map of values. */ static final int TYPE_CODE_MULTISET = -5; /** * Multimap type code, followed by a map of values. */ static final int TYPE_CODE_LIST_MULTIMAP = -6; /** * SetMultimap type code, followed by a map of values. */ static final int TYPE_CODE_SET_MULTIMAP = -7; /** * Bimap type code, followed by a map of values. */ static final int TYPE_CODE_BIMAP = -8; /** * Table type code. */ static final int TYPE_CODE_TABLE = -9; /** * Optional (Guava) type code, followed by a value, where a null value means empty. */ static final int TYPE_CODE_GUAVA_OPTIONAL = -10; /** * Grid type code. */ static final int TYPE_CODE_GRID = -11; /** * Object[] type code, followed by an array of values. */ static final int TYPE_CODE_OBJECT_ARRAY = -12; /** * String[] type code, followed by an array of values. */ static final int TYPE_CODE_STRING_ARRAY = -13; //----------------------------------------------------------------------- /** * Converts a byte to a hex string for debugging. * * @param b the byte * @return the two character hex equivalent, not null */ static String toHex(int b) { return String.format("%02X", (byte) b); } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/BeanPackInput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; /** * Receives and processes BeanPack data. *

* This interprets based on the data in the input, and does not interpret data into beans. */ abstract class BeanPackInput extends BeanPack { /** * The stream to read. */ private final DataInputStream input; /** * The type definitions. */ private final List typeDefinitions = new ArrayList<>(); /** * The value definitions. */ private final List valueDefinitions = new ArrayList<>(); /** * Creates an instance. * * @param bytes the bytes to read, not null */ BeanPackInput(byte[] bytes) { this(new DataInputStream(new ByteArrayInputStream(bytes))); } /** * Creates an instance. * * @param stream the stream to read from, not null */ BeanPackInput(DataInputStream stream) { this.input = stream; } //----------------------------------------------------------------------- /** * Reads all the data in the stream, closing the stream. */ void readAll() { try { try { acceptObject(); } finally { input.close(); } } catch (IOException ex) { throw new IllegalStateException(ex); } } //------------------------------------------------------------------------- private Object acceptObject() throws IOException { var next = input.readByte(); return readObject(next); } //----------------------------------------------------------------------- Object readObject(byte typeByte) throws IOException { handleObjectStart(); if (typeByte >= MIN_FIX_INT) { // no need to check for b <= MAX_FIX_INT handleInt(typeByte); return typeByte; } else if (typeByte >= MIN_FIX_STR && typeByte <= MAX_FIX_STR) { return parseString(typeByte - MIN_FIX_STR); } else if (typeByte >= MIN_FIX_ARRAY && typeByte <= MAX_FIX_ARRAY) { return parseArray(typeByte - MIN_FIX_ARRAY); } else if (typeByte >= MIN_FIX_MAP && typeByte <= MAX_FIX_MAP) { return parseMap(typeByte - MIN_FIX_MAP); } else { return switch (typeByte) { case MAP_8 -> parseMap(input.readUnsignedByte()); case MAP_16 -> parseMap(input.readUnsignedShort()); case MAP_32 -> parseMap(input.readInt()); case ARRAY_8 -> parseArray(input.readUnsignedByte()); case ARRAY_16 -> parseArray(input.readUnsignedShort()); case ARRAY_32 -> parseArray(input.readInt()); case STR_8 -> parseString(input.readUnsignedByte()); case STR_16 -> parseString(input.readUnsignedShort()); case STR_32 -> parseString(input.readInt()); case NULL -> parseNull(); case FALSE -> parseBoolean(false); case TRUE -> parseBoolean(true); case UNUSED -> parseUnknown(typeByte); case FLOAT_32 -> parseFloat(input.readFloat()); case DOUBLE_INT_8 -> parseDouble(input.readByte()); case DOUBLE_64 -> parseDouble(input.readDouble()); case CHAR_16 -> parseChar(input.readChar()); case BYTE_8 -> parseByte(input.readByte()); case SHORT_16 -> parseShort(input.readShort()); case INT_16 -> parseInt(input.readShort()); case INT_32 -> parseInt(input.readInt()); case LONG_8 -> parseLong(input.readByte()); case LONG_16 -> parseLong(input.readShort()); case LONG_32 -> parseLong(input.readInt()); case LONG_64 -> parseLong(input.readLong()); case DATE_PACKED -> parseDatePacked(); case DATE -> parseDate(); case TIME -> parseTime(); case INSTANT -> parseInstant(); case DURATION -> parseDuration(); case BIN_8 -> parseByteArray(input.readUnsignedByte()); case BIN_16 -> parseByteArray(input.readUnsignedShort()); case BIN_32 -> parseByteArray(input.readInt()); case DOUBLE_ARRAY_8 -> parseDoubleArray(input.readUnsignedByte()); case DOUBLE_ARRAY_16 -> parseDoubleArray(input.readUnsignedShort()); case DOUBLE_ARRAY_32 -> parseDoubleArray(input.readInt()); case TYPE_DEFN_8 -> parseTypeName(input.readUnsignedByte()); case TYPE_DEFN_16 -> parseTypeName(input.readUnsignedShort()); case TYPE_REF_8 -> parseTypeReference(input.readByte()); case TYPE_REF_16 -> parseTypeReference(input.readUnsignedShort()); case BEAN_DEFN -> parseBean(input.readUnsignedByte()); case VALUE_DEFN -> parseValueDefinition(); case VALUE_REF_8 -> parseValueReference(input.readUnsignedByte()); case VALUE_REF_16 -> parseValueReference(input.readUnsignedShort()); case VALUE_REF_24 -> parseValueReference((input.readUnsignedByte() << 16) + input.readUnsignedShort()); default -> parseUnknown(typeByte); }; } } //------------------------------------------------------------------------- private Object parseMap(int size) throws IOException { handleMapHeader(size); for (var i = 0; i < size; i++) { readMapKey(); readMapValue(); } handleMapFooter(); return ""; // maps are not cached as values, so this map must actually be a bean } Object readMapKey() throws IOException { return acceptObject(); } Object readMapValue() throws IOException { return acceptObject(); } private Object parseArray(int size) throws IOException { handleArrayHeader(size); for (var i = 0; i < size; i++) { readArrayItem(); } handleArrayFooter(); return ""; // maps are not cached as values, so this map must actually be a bean } Object readArrayItem() throws IOException { return acceptObject(); } private Object parseBean(int size) throws IOException { handleBeanHeader(size); for (var i = 0; i < size * 2; i++) { readBeanItem(); } handleBeanFooter(); return ""; } Object readBeanItem() throws IOException { return acceptObject(); } private Object readAnnotatedValue() throws IOException { return acceptObject(); } //------------------------------------------------------------------------- private Object parseNull() throws IOException { handleNull(); return null; } private Object parseBoolean(boolean value) throws IOException { handleBoolean(value); return value; } private Object parseUnknown(byte value) throws IOException { handleUnknown(value); return null; } private Object parseFloat(float value) throws IOException { handleFloat(value); return null; } private Object parseDouble(double value) throws IOException { handleDouble(value); return null; } private Object parseChar(char value) throws IOException { handleChar(value); return null; } private Object parseByte(byte value) throws IOException { handleByte(value); return value; } private Object parseShort(short value) throws IOException { handleShort(value); return value; } private Object parseInt(int value) throws IOException { handleInt(value); return value; } private Object parseLong(long value) throws IOException { handleLong(value); return value; } private String parseString(int size) throws IOException { if (size < 0) { throw new IllegalStateException("String too large"); } var bytes = new byte[size]; input.readFully(bytes); var str = new String(bytes, UTF_8); handleString(str); if (str.length() >= MIN_LENGTH_STR_VALUE) { valueDefinitions.add(str); } return str; } private LocalDate parseDatePacked() throws IOException { var packed = input.readUnsignedShort(); var dom = packed & 31; var ym = packed >> 5; var date = LocalDate.of((ym / 12) + 2000, (ym % 12) + 1, dom); handleDate(date); return date; } private LocalDate parseDate() throws IOException { var upper = input.readInt(); var lower = input.readUnsignedByte(); var year = upper >> 1; var month = ((upper & 1) << 3) + (lower >>> 5); var dom = lower & 31; var date = LocalDate.of(year, month, dom); handleDate(date); return date; } private LocalTime parseTime() throws IOException { var upper = input.readUnsignedShort(); var lower = Integer.toUnsignedLong(input.readInt()); var nod = ((long) upper << 32) + lower; var time = LocalTime.ofNanoOfDay(nod); handleTime(time); return time; } private Instant parseInstant() throws IOException { var second = input.readLong(); var nanos = input.readInt(); var instant = Instant.ofEpochSecond(second, nanos); handleInstant(instant); return instant; } private Duration parseDuration() throws IOException { var seconds = input.readLong(); var nanos = input.readInt(); var duration = Duration.ofSeconds(seconds, nanos); handleDuration(duration); return duration; } //----------------------------------------------------------------------- private byte[] parseByteArray(int size) throws IOException { var bytes = new byte[size]; input.readFully(bytes); handleBinary(bytes); return bytes; } private double[] parseDoubleArray(int size) throws IOException { var values = new double[size]; for (int i = 0; i < size; i++) { values[i] = input.readDouble(); } handleDoubleArray(values); return values; } //------------------------------------------------------------------------- private Object parseTypeName(int size) throws IOException { var bytes = new byte[size]; input.readFully(bytes); var typeName = new String(bytes, UTF_8); handleTypeName(typeName); typeDefinitions.add(typeName); return readAnnotatedValue(); } private Object parseTypeReference(int ref) throws IOException { var typeName = switch (ref) { case TYPE_CODE_LIST -> "List"; case TYPE_CODE_SET -> "Set"; case TYPE_CODE_MAP -> "Map"; case TYPE_CODE_OPTIONAL -> "Optional"; case TYPE_CODE_MULTISET -> "Multiset"; case TYPE_CODE_LIST_MULTIMAP -> "ListMultimap"; case TYPE_CODE_SET_MULTIMAP -> "SetMultimap"; case TYPE_CODE_BIMAP -> "BiMap"; case TYPE_CODE_TABLE -> "Table"; case TYPE_CODE_GUAVA_OPTIONAL -> "List"; case TYPE_CODE_GRID -> "Grid"; case TYPE_CODE_OBJECT_ARRAY -> "Object[]"; case TYPE_CODE_STRING_ARRAY -> "String[]"; default -> ref >= 0 ? typeDefinitions.get(ref) : "Unknown"; }; handleTypeReference(ref, typeName); return readAnnotatedValue(); } private Object parseValueDefinition() throws IOException { handleValueDefinition(); var value = readAnnotatedValue(); valueDefinitions.add(value); return value; } private Object parseValueReference(int ref) { var value = valueDefinitions.get(ref); handleValueReference(ref, value); return value; } //------------------------------------------------------------------------- void handleObjectStart() { } void handleMapHeader(int size) { } void handleMapFooter() { } void handleArrayHeader(int size) { } void handleArrayFooter() { } void handleString(String str) { } void handleNull() { } void handleBoolean(boolean bool) { } void handleFloat(float value) { } void handleDouble(double value) { } void handleChar(char value) { } void handleByte(byte value) { } void handleShort(short value) { } void handleInt(int value) { } void handleLong(long value) { } void handleDate(LocalDate date) { } void handleTime(LocalTime time) { } void handleInstant(Instant instant) { } void handleDuration(Duration duration) { } void handleBinary(byte[] bytes) { } void handleDoubleArray(double[] values) { } void handleTypeName(String typeName) throws IOException { } void handleTypeReference(int ref, String typeName) throws IOException { } void handleBeanHeader(int propertyCount) throws IOException { } void handleBeanFooter() throws IOException { } void handleValueDefinition() throws IOException { } void handleValueReference(int ref, Object value) { } void handleUnknown(byte b) { } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/BeanPackOutput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; import org.joda.beans.ResolvedType; /** * Outputter for BeanPack data, which is derived from ideas in MsgPack. */ final class BeanPackOutput extends BeanPack { /** * Mask to check if value is a small positive integer, from 0 to 127 inclusive. */ private static final int MASK_SMALL_INT_POSITIVE = 0xFFFFFF80; /** * The stream to write to. */ private final DataOutputStream output; /** * Creates an instance. * * @param stream the stream to write to, not null */ BeanPackOutput(OutputStream stream) { this.output = new DataOutputStream(stream); } //----------------------------------------------------------------------- /** * Writes a null. * * @throws IOException if an error occurs */ void writeNull() throws IOException { output.writeByte(NULL); } /** * Writes a boolean. * * @param value the value * @throws IOException if an error occurs */ void writeBoolean(boolean value) throws IOException { if (value) { output.writeByte(TRUE); } else { output.writeByte(FALSE); } } /** * Writes a float. * * @param value the value * @throws IOException if an error occurs */ void writeFloat(float value) throws IOException { output.writeByte(FLOAT_32); output.writeFloat(value); } /** * Writes a double. * * @param value the value * @throws IOException if an error occurs */ void writeDouble(double value) throws IOException { var intValue = (int) value; if (value == intValue && intValue <= Byte.MAX_VALUE && intValue >= Byte.MIN_VALUE && Double.compare(value, -0d) != 0) { output.writeByte(DOUBLE_INT_8); output.writeByte(intValue); } else { output.writeByte(DOUBLE_64); output.writeDouble(value); } } /** * Writes a char. * * @param value the value * @throws IOException if an error occurs */ void writeChar(char value) throws IOException { output.writeByte(CHAR_16); output.writeChar(value); } /** * Writes a byte. * * @param value the value * @throws IOException if an error occurs */ void writeByte(byte value) throws IOException { output.writeByte(BYTE_8); output.writeByte(value); } /** * Writes a short. * * @param value the value * @throws IOException if an error occurs */ void writeShort(short value) throws IOException { output.writeByte(SHORT_16); output.writeShort(value); } /** * Writes an int. * * @param value the value * @throws IOException if an error occurs */ void writeInt(int value) throws IOException { if ((value & MASK_SMALL_INT_POSITIVE) == 0) { output.writeByte(value); } else if (value >= 0) { if (value <= Short.MAX_VALUE) { output.writeByte(INT_16); output.writeShort((short) value); } else { output.writeByte(INT_32); output.writeInt(value); } } else { if (value >= MIN_FIX_INT) { output.writeByte(value); } else if (value >= Short.MIN_VALUE) { output.writeByte(INT_16); output.writeShort((short) value); } else { output.writeByte(INT_32); output.writeInt(value); } } } /** * Writes a long. * * @param value the value * @throws IOException if an error occurs */ void writeLong(long value) throws IOException { if (value >= 0) { if (value <= Byte.MAX_VALUE) { output.writeByte(LONG_8); output.writeByte((byte) value); } else if (value <= Short.MAX_VALUE) { output.writeByte(LONG_16); output.writeShort((short) value); } else if (value <= Integer.MAX_VALUE) { output.writeByte(LONG_32); output.writeInt((int) value); } else { output.writeByte(LONG_64); output.writeLong(value); } } else { if (value >= Byte.MIN_VALUE) { output.writeByte(LONG_8); output.writeByte((byte) value); } else if (value >= Short.MIN_VALUE) { output.writeByte(LONG_16); output.writeShort((short) value); } else if (value >= Integer.MIN_VALUE) { output.writeByte(LONG_32); output.writeInt((int) value); } else { output.writeByte(LONG_64); output.writeLong(value); } } } //------------------------------------------------------------------------- /** * Writes a date. * * @param date the date * @throws IOException if an error occurs */ void writeDate(LocalDate date) throws IOException { var year = date.getYear(); var month = date.getMonthValue(); var dom = date.getDayOfMonth(); if (year >= 2000 && year <= 2169) { var ym2000 = (year - 2000) * 12 + (month - 1); output.write(DATE_PACKED); var packed = (ym2000 << 5) + dom; output.writeShort(packed); } else { output.write(DATE); var packed = (((long) year) << 9) + (month << 5) + dom; output.writeInt((int) (packed >> 8)); output.writeByte((byte) (packed & 0xFF)); } } /** * Writes a time. * * @param time the time * @throws IOException if an error occurs */ void writeTime(LocalTime time) throws IOException { var nod = time.toNanoOfDay(); var upper = (int) (nod >>> 32); var lower = (int) (nod & 0xFFFFFFFFL); output.write(TIME); output.writeShort(upper); output.writeInt(lower); } /** * Writes an instant. * * @param instant the instant * @throws IOException if an error occurs */ void writeInstant(Instant instant) throws IOException { output.write(INSTANT); output.writeLong(instant.getEpochSecond()); output.writeInt(instant.getNano()); } /** * Writes a duration. * * @param duration the instant * @throws IOException if an error occurs */ void writeDuration(Duration duration) throws IOException { output.write(DURATION); output.writeLong(duration.getSeconds()); output.writeInt(duration.getNano()); } //------------------------------------------------------------------------- /** * Writes a byte[]. * * @param bytes the bytes, not null * @throws IOException if an error occurs */ void writeBytes(byte[] bytes) throws IOException { // positive numbers only var size = bytes.length; if (size <= 0xFF) { output.writeByte(BIN_8); output.writeByte(size); } else if (size <= 0xFFFF) { output.writeByte(BIN_16); output.writeShort(size); } else { output.writeByte(BIN_32); output.writeInt(size); } output.write(bytes); } /** * Writes a double[]. * * @param values the values, not null * @throws IOException if an error occurs */ void writeDoubles(double[] values) throws IOException { // positive numbers only var size = values.length; if (size <= 0xFF) { output.writeByte(DOUBLE_ARRAY_8); output.writeByte(size); } else if (size <= 0xFFFF) { output.writeByte(DOUBLE_ARRAY_16); output.writeShort(size); } else { output.writeByte(DOUBLE_ARRAY_32); output.writeInt(size); } for (double value : values) { output.writeDouble(value); } } //------------------------------------------------------------------------- /** * Writes a map header. * * @param size the size * @throws IOException if an error occurs */ void writeMapHeader(int size) throws IOException { // positive numbers only if (size <= 12) { output.writeByte(MIN_FIX_MAP + size); } else if (size <= 0xFF) { output.writeByte(MAP_8); output.writeByte(size); } else if (size <= 0xFFFF) { output.writeByte(MAP_16); output.writeShort(size); } else { output.writeByte(MAP_32); output.writeInt(size); } } /** * Writes an array header. * * @param size the size * @throws IOException if an error occurs */ void writeArrayHeader(int size) throws IOException { // positive numbers only if (size <= 12) { output.writeByte(MIN_FIX_ARRAY + size); } else if (size <= 0xFF) { output.writeByte(ARRAY_8); output.writeByte(size); } else if (size <= 0xFFFF) { output.writeByte(ARRAY_16); output.writeShort(size); } else { output.writeByte(ARRAY_32); output.writeInt(size); } } /** * Writes a String. * * @param value the value * @throws IOException if an error occurs */ void writeString(String value) throws IOException { // Java 21 performance testing showed manually converting to UTF-8 to be slower var bytes = value.getBytes(UTF_8); var size = bytes.length; if (size <= (MAX_FIX_STR - MIN_FIX_STR)) { output.writeByte(MIN_FIX_STR + size); } else { writeStringHeaderLarge(size); } output.write(bytes); } // separate out larger strings, which may benefit hotspot private void writeStringHeaderLarge(int size) throws IOException { // positive numbers only if (size <= 0xFF) { output.writeByte(STR_8); output.writeByte(size); } else if (size <= 0xFFFF) { output.writeByte(STR_16); output.writeShort(size); } else { output.writeByte(STR_32); output.writeInt(size); } } //------------------------------------------------------------------------- /** * Writes a type name. *

* The type name is a class name, not a {@link ResolvedType}. * * @param className the class name * @throws IOException if an error occurs */ void writeTypeName(String className) throws IOException { // written directly, as this is not part of the value definition setup var bytes = className.getBytes(UTF_8); if (bytes.length <= 0xFF) { output.write(TYPE_DEFN_8); output.writeByte(bytes.length); } else { // assume type name length will be < 0xFFFF output.write(TYPE_DEFN_16); output.writeShort(bytes.length); } output.write(bytes); } /** * Writes a type reference. * * @param ref the reference * @throws IOException if an error occurs */ void writeTypeReference(int ref) throws IOException { // allow negative numbers >= -128 if (ref <= 0x7F) { output.write(TYPE_REF_8); output.writeByte(ref); } else { output.write(TYPE_REF_16); output.writeShort(ref); } } /** * Writes a bean definition header. * * @param propertyCount the count of properties, must be 0 to 255 * @throws IOException if an error occurs */ void writeBeanDefinitionHeader(int propertyCount) throws IOException { // 0 to 255 output.write(BEAN_DEFN); output.writeByte(propertyCount); } /** * Writes a value definition header. * * @throws IOException if an error occurs */ void writeValueDefinitionHeader() throws IOException { output.write(VALUE_DEFN); } /** * Writes a value reference. * * @param ref the reference * @throws IOException if an error occurs */ void writeValueReference(int ref) throws IOException { // positive numbers only if (ref <= 0xFF) { output.write(VALUE_REF_8); output.writeByte(ref); } else if (ref <= 0xFFFF) { output.write(VALUE_REF_16); output.writeShort(ref); } else { output.write(VALUE_REF_24); output.writeByte(ref >>> 16); output.writeShort(ref & 0xFFFF); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/BeanPackVisualizer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.IOException; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; /** * Allows BeanPack data to be visualized. */ final class BeanPackVisualizer extends BeanPackInput { /** * The current indent. */ private String indent = ""; /** * The buffer. */ private final StringBuilder buf = new StringBuilder(1024); /** * Creates an instance. * * @param bytes the bytes to read, not null */ BeanPackVisualizer(byte[] bytes) { super(bytes); } //----------------------------------------------------------------------- /** * Visualizes the data in the stream. */ String visualizeData() { try { readAll(); return buf.toString(); } catch (Exception ex) { return buf.append("!!ERROR!!").append(System.lineSeparator()).append(ex.toString()).toString(); } } //----------------------------------------------------------------------- @Override Object readMapKey() throws IOException { indent = indent + "= "; var value = super.readMapKey(); indent = indent.substring(0, indent.length() - 2); return value; } @Override Object readMapValue() throws IOException { indent = indent + " "; var value = super.readMapValue(); indent = indent.substring(0, indent.length() - 2); return value; } @Override Object readArrayItem() throws IOException { indent = indent + "- "; var value = super.readArrayItem(); indent = indent.substring(0, indent.length() - 2); return value; } @Override Object readBeanItem() throws IOException { indent = indent + "- "; var value = super.readBeanItem(); indent = indent.substring(0, indent.length() - 2); return value; } @Override void handleObjectStart() { buf.append(indent); indent = indent.replace("-", " ").replace("=", " "); } //------------------------------------------------------------------------- @Override void handleNull() { buf.append("null").append(System.lineSeparator()); } @Override void handleBoolean(boolean bool) { buf.append(bool).append(System.lineSeparator()); } @Override void handleFloat(float value) { buf.append("flt ").append(value).append(System.lineSeparator()); } @Override void handleDouble(double value) { buf.append("dbl ").append(value).append(System.lineSeparator()); } @Override void handleChar(char value) { buf.append("chr ").append(value).append(System.lineSeparator()); } @Override void handleByte(byte value) { buf.append("byt ").append(value).append(System.lineSeparator()); } @Override void handleShort(short value) { buf.append("sht ").append(value).append(System.lineSeparator()); } @Override void handleInt(int value) { buf.append("int ").append(value).append(System.lineSeparator()); } @Override void handleLong(long value) { buf.append("lng ").append(value).append(System.lineSeparator()); } //------------------------------------------------------------------------- @Override void handleDate(LocalDate date) { buf.append(date).append(System.lineSeparator()); } @Override void handleTime(LocalTime time) { buf.append(time).append(System.lineSeparator()); } @Override void handleInstant(Instant instant) { buf.append(instant).append(System.lineSeparator()); } @Override void handleDuration(Duration duration) { buf.append(duration).append(System.lineSeparator()); } //------------------------------------------------------------------------- @Override void handleMapHeader(int size) { buf.append("map (").append(size).append(")").append(System.lineSeparator()); } @Override void handleArrayHeader(int size) { buf.append("arr (").append(size).append(")").append(System.lineSeparator()); } @Override void handleString(String str) { buf.append("str '").append(str).append('\'').append(System.lineSeparator()); } @Override void handleBinary(byte[] bytes) { buf.append("bin '"); for (byte b : bytes) { buf.append(toHex(b)); } buf.append("'").append(System.lineSeparator()); } @Override void handleDoubleArray(double[] values) { buf.append("dbl ["); for (int i = 0; i < values.length; i++) { if (i > 0) { buf.append(System.lineSeparator()).append(" "); } for (int j = 0; j < 8 && i < values.length; j++, i++) { if (j > 0) { buf.append(','); } buf.append(values[i]); } } buf.append("]").append(System.lineSeparator()); } //------------------------------------------------------------------------- @Override void handleTypeName(String typeName) throws IOException { buf.append("@type ").append(typeName).append(System.lineSeparator()); } @Override void handleTypeReference(int ref, String typeName) throws IOException { var str = ref < 0 ? typeName : ref + " " + typeName; buf.append("@typeref ").append(str).append(System.lineSeparator()); } @Override void handleBeanHeader(int propertyCount) throws IOException { buf.append("bean (").append(propertyCount).append(")").append(System.lineSeparator()); } @Override void handleValueDefinition() throws IOException { buf.append("@value ").append(System.lineSeparator()); } @Override void handleValueReference(int ref, Object value) { buf.append("ref ").append(ref).append(" '").append(value).append('\'').append(System.lineSeparator()); } //------------------------------------------------------------------------- @Override void handleUnknown(byte b) { buf.append("Unknown - ").append(String.format("%02X ", b)).append(System.lineSeparator()); } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/BeanReferences.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import static java.util.Collections.reverseOrder; import static java.util.Comparator.comparingInt; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerIterator; import org.joda.beans.ser.SerOptional; /** * Stores information on the references in a bean. */ final class BeanReferences { private static final Set> NON_REFERENCED = Set.of( Long.class, Integer.class, Short.class, Byte.class, Double.class, Float.class, Boolean.class, Character.class, byte[].class); /** * The settings. */ private final JodaBeanSer settings; /** * The classes that are being serialized. */ private final Map, ClassInfo> classes = new HashMap<>(); /** * The amount of time each class needs to have its type serialized, linked for stability. */ private final Map, Integer> classSerializationCount = new LinkedHashMap<>(); /** * The sorted class infos. */ private final List classInfoList = new ArrayList<>(); /** * The serialized objects that are repeated and require references. */ private final Map refs = new HashMap<>(); // finds static BeanReferences find(ImmutableBean root, JodaBeanSer settings) { var references = new BeanReferences(settings); references.findReferences(root); return references; } // creates an instance private BeanReferences(JodaBeanSer settings) { this.settings = settings; } //----------------------------------------------------------------------- // finds classes and references within the bean private void findReferences(ImmutableBean root) { // handle root bean classes.put(root.getClass(), classInfoFromMetaBean(root.metaBean())); classSerializationCount.put(root.getClass(), 1); // recursively check object graph var objects = new LinkedHashMap(); findReferencesBean(root, root.getClass(), objects, null); // build up the list of references, but only for those instances that are repeated var refEntries = objects.entrySet().stream() .filter(entry -> entry.getValue() > 1) .sorted(reverseOrder(comparingInt(Map.Entry::getValue))) .toList(); for (var entry : refEntries) { var value = entry.getKey(); var realType = value.getClass(); // simple types do not need references if (!NON_REFERENCED.contains(realType)) { refs.put(value, new Ref(false, refs.size())); } } // reorder classes so the most repeated serialized names have the lowest number (hence the shortest extension) this.classInfoList.addAll(classSerializationCount.entrySet().stream() .sorted(reverseOrder(comparingInt(Map.Entry::getValue))) .map(entry -> classes.get(entry.getKey())) .toList()); // adjust the position in the ClassInfo instance for (var position = 0; position < classInfoList.size(); position++) { var classInfo = classInfoList.get(position); classInfo.position = position; } } // recursively find the references private void findReferencesBean( Object base, Class declaredClass, Map objects, SerIterator parentIterator) { if (base == null) { return; } // has this object been seen before, if so no need to check it again if (objects.compute(base, BeanReferences::incrementOrOne) > 1) { // shouldn't try and reuse references to collections if (!(base instanceof Bean) && parentIterator != null) { var childIterator = settings.getIteratorFactory().createChild(base, parentIterator); if (childIterator != null) { findReferencesIterable(childIterator, objects); } } return; } if (base instanceof Bean bean) { addClassInfo(base, declaredClass); if (settings.getConverter().isConvertible(bean.getClass())) { return; } for (var prop : bean.metaBean().metaPropertyIterable()) { if (settings.isSerialized(prop)) { var value = prop.get(bean); var type = SerOptional.extractType(prop, base.getClass()); if (value != null) { var itemIterator = settings.getIteratorFactory().create(value, prop, bean.getClass()); if (itemIterator != null) { if (itemIterator.metaTypeRequired()) { objects.compute(itemIterator.metaTypeName(), BeanReferences::incrementOrOne); } findReferencesIterable(itemIterator, objects); } else { findReferencesBean(value, type, objects, null); } } } } } else if (parentIterator != null) { var childIterator = settings.getIteratorFactory().createChild(base, parentIterator); if (childIterator != null) { // shouldn't try and reuse references to collections findReferencesIterable(childIterator, objects); } else { addClassInfo(base, declaredClass); } } else { addClassInfo(base, declaredClass); } } // recursively find the references in an iterable private void findReferencesIterable(SerIterator itemIterator, Map objects) { switch (itemIterator.category()) { case COLLECTION -> { while (itemIterator.hasNext()) { itemIterator.next(); findReferencesBean(itemIterator.value(), itemIterator.valueType(), objects, itemIterator); } } case COUNTED -> { while (itemIterator.hasNext()) { itemIterator.next(); findReferencesBean(itemIterator.value(), itemIterator.valueType(), objects, itemIterator); } } case MAP -> { while (itemIterator.hasNext()) { itemIterator.next(); findReferencesBean(itemIterator.key(), itemIterator.keyType(), objects, null); findReferencesBean(itemIterator.value(), itemIterator.valueType(), objects, itemIterator); } } case TABLE -> { while (itemIterator.hasNext()) { itemIterator.next(); findReferencesBean(itemIterator.key(), itemIterator.keyType(), objects, null); findReferencesBean(itemIterator.column(), itemIterator.columnType(), objects, null); findReferencesBean(itemIterator.value(), itemIterator.valueType(), objects, itemIterator); } } case GRID -> { while (itemIterator.hasNext()) { itemIterator.next(); findReferencesBean(itemIterator.value(), itemIterator.valueType(), objects, itemIterator); } } } } // add to list of known classes private void addClassInfo(Object value, Class declaredClass) { if (value instanceof Bean bean) { if (!(value instanceof ImmutableBean)) { throw new IllegalArgumentException( "Can only serialize immutable beans in referencing binary format: " + value.getClass().getName()); } var isConvertible = settings.getConverter().isConvertible(value.getClass()); if (declaredClass.equals(value.getClass()) && (classes.containsKey(value.getClass()) || isConvertible)) { return; } // don't need meta-property info if it's a convertible type if (isConvertible) { addClassInfoForEffectiveType(value); } else { var classInfo = classInfoFromMetaBean(bean.metaBean()); addClassInfoAndIncrementCount(value.getClass(), classInfo); } } else if (declaredClass == Object.class && !value.getClass().equals(String.class)) { addClassInfoForEffectiveType(value); } else if (!settings.getConverter().isConvertible(declaredClass)) { addClassInfoForEffectiveType(value); } } private void addClassInfoForEffectiveType(Object value) { var effectiveType = settings.getConverter().findTypedConverter(value.getClass()).getEffectiveType(); var classInfo = new ClassInfo(effectiveType, List.of()); addClassInfoAndIncrementCount(effectiveType, classInfo); } // adds the class, incrementing the number of times it is used private void addClassInfoAndIncrementCount(Class type, ClassInfo classInfo) { classes.putIfAbsent(type, classInfo); classSerializationCount.compute(type, BeanReferences::incrementOrOne); } // converts a meta-bean to a ClassInfo private ClassInfo classInfoFromMetaBean(MetaBean metaBean) { var metaProperties = new ArrayList>(); for (var metaProp : metaBean.metaPropertyIterable()) { if (settings.isSerialized(metaProp)) { metaProperties.add(metaProp); } } // Positions get recreated when all classes have been recorded return new ClassInfo(metaBean.beanType(), metaProperties); } // Used in Map#compute so we can initialise all the values to one and then increment private static int incrementOrOne(@SuppressWarnings("unused") Object k, Integer i) { return i == null ? 1 : Math.addExact(i, 1); } //----------------------------------------------------------------------- // gets the map of references Map getReferences() { return refs; } List getClassInfoList() { return classInfoList; } // lookup the class info by type ClassInfo getClassInfo(Class effectiveType) { var classInfo = classes.get(effectiveType); if (classInfo == null) { throw new IllegalStateException( "Tried to serialise class that wasn't present in bean on first pass: " + effectiveType.getName()); } return classInfo; } // CSOFF //----------------------------------------------------------------------- // The info needed to serialize instances of a class with a reference to the initially serialized class definition static final class ClassInfo { // The class itself - not necessary for serialization but here for easier inspection final Class type; // The meta-properties (empty if not a bean) in the order in which they need to be serialized final List> metaProperties; // The position in the initial class definition list, lower means serialized more often int position; private ClassInfo(Class type, List> metaProperties) { this.type = type; this.metaProperties = metaProperties; this.position = -1; } @Override public String toString() { return "ClassInfo{" + "position=" + position + ", type=" + type + ", metaProperties=" + metaProperties + '}'; } } //----------------------------------------------------------------------- // The reference itself (position) plus whether it has previously been serialized static final class Ref { boolean hasBeenSerialized; final int position; private Ref(boolean hasBeenSerialized, int position) { this.hasBeenSerialized = hasBeenSerialized; this.position = position; } void sent() { hasBeenSerialized = true; } @Override public String toString() { return "Ref{" + "hasBeenSerialized=" + hasBeenSerialized + ", position=" + position + '}'; } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanBinFormat.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import org.joda.beans.ser.JodaBeanSer; /** * Provides control over the binary format. * * @since 3.0.0 */ public enum JodaBeanBinFormat { /** * The Standard format, version 1. *

* The binary format is based on MessagePack v2.0. * Each bean is output as a map using the property name. *

* Most simple types, defined by Joda-Convert, are output as MessagePack strings. * However, MessagePack nil, boolean, float, integral and bin types are also used * for null, byte[] and the Java numeric primitive types (excluding char). *

* Beans are output using MessagePack maps where the key is the property name. * Collections are output using MessagePack maps or arrays. * Multisets are output as a map of value to count. *

* If a collection contains a collection then addition meta-type information is * written to aid with deserialization. * At this level, the data read back may not be identical to that written. *

* Where necessary, the Java type is sent using an 'ext' entity. * Three 'ext' types are used, one each for beans, meta-type and simple. * The class name is passed as the 'ext' data. * The 'ext' value is sent as an additional key-value pair for beans, with the * 'ext' as the key and 'nil' as the value. Where the additional type information * is not about a bean, a tuple is written using a size 1 map where the key is the * 'ext' data and the value is the data being annotated. *

* Type names are shortened by the package of the root type if possible. * Certain basic types are also handled, such as String, Integer, File and URI. */ STANDARD(1), /** * The Referencing format, version 2. *

* The referencing format is based on the standard format. * As a more complex format, it is intended to be consumed only by Joda-Beans * (whereas the standard format could be consumed by any consumer using MsgPack). * Thus this format is not fully documented and may change over time. *

* The referencing format only supports serialization of instances of {@code ImmutableBean} * and other basic types. If any mutable beans are encountered during traversal an exception will be thrown. *

* An initial pass of the bean is used to build up a map of unique immutable beans * and unique immutable instances of other classes (based on an equality check). * Then the class and property names for each bean class is serialized up front as a map of class name to list of * property names, along with class information for any class where type information would be required when parsing * and is not available on the metabean for the enclosing bean object. *

* Each unique immutable bean is output as a list of each property value using the fixed * property order previously serialized. Subsequent instances of unique objects (defined by an * equality check) are replaced by references to the first serialized instance. *

* The Java type names are sent using an 'ext' entity. * Five 'ext' types are used, one each for beans, meta-type and simple, reference keys and reference lookups. * The class name is passed as the 'ext' data. * The 'ext' value is sent as the first item in an array of property values for beans, an integer referring to the * location in the initial class mapping. * Where the additional type information is not about a bean, a tuple is written using a size 1 map where the key is * the 'ext' data and the value is the data being annotated. *

* For references, when an object will be referred back to it is written as a map of size one with 'ext' as the key * and the object that should be referred to as the value. * When that same object is referred back to it is written as 'ext' with the data from the initial 'ext'. */ REFERENCING(2), /** * Packed format, version 3. *

* This format uses a structure called BeanPack that is similar to MessagePack, but distinctly different. * The exact format is not specified and may change over time. * Types, bean definitions and Joda-Convert values are captured the first time they are found and then used by reference. * In addition, {@link JodaBeanSer#getBeanValueClasses()} is taken into account, with instances of the specified * value classes being deduplicated in the binary form. (Types and values are deduplicated automatically, beans * are only deduplicated as per {@code JodaBeanSer.getBeanValueClasses()}). */ PACKED(3); /** * The format version. */ private final int version; private JodaBeanBinFormat(int version) { this.version = version; } /** * Returns the version number used to identify the format in the file. * * @return the version */ public int version() { return version; } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanBinReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.InputStream; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.ser.JodaBeanSer; /** * Provides the ability for a Joda-Bean to read from binary formats. *

* This class is immutable and may be used from multiple threads. *

* The binary formats are defined by {@link JodaBeanBinWriter}. */ public class JodaBeanBinReader extends MsgPack { /** * Settings. */ private final JodaBeanSer settings; //----------------------------------------------------------------------- /** * Visualizes the binary data. * * @param input the input bytes, not null * @return the visualization */ public static String visualize(byte[] input) { if (input.length >= 2 && input[1] == 3) { return new BeanPackVisualizer(input).visualizeData(); } return new MsgPackVisualizer(input).visualizeData(); } //----------------------------------------------------------------------- /** * Creates an instance. * * @param settings the settings, not null */ public JodaBeanBinReader(JodaBeanSer settings) { this.settings = Objects.requireNonNull(settings, "settings must not be null"); } //----------------------------------------------------------------------- /** * Reads and parses to a bean. * * @param input the input bytes, not null * @return the bean, not null */ public Bean read(byte[] input) { return read(input, Bean.class); } /** * Reads and parses to a bean. * * @param the root type * @param input the input bytes, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(byte[] input, Class rootType) { Objects.requireNonNull(input, "input must not be null"); return read(new ByteArrayInputStream(input), rootType); } /** * Reads and parses to a bean. * * @param input the input reader, not null * @return the bean, not null */ public Bean read(InputStream input) { return read(input, Bean.class); } /** * Reads and parses to a bean. *

* Unusually for a method of this type, it closes the input stream. * * @param the root type * @param input the input stream, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(InputStream input, Class rootType) { Objects.requireNonNull(input, "input must not be null"); Objects.requireNonNull(rootType, "rootType must not be null"); try { try (input) { var dataInput = input instanceof DataInputStream din ? din : new DataInputStream(input); return parseVersion(dataInput, rootType); } } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } //----------------------------------------------------------------------- // parses the version private T parseVersion(DataInputStream input, Class declaredType) throws Exception { // root array int arrayByte = input.readByte(); int versionByte = input.readByte(); switch (versionByte) { case 1: if (arrayByte != MIN_FIX_ARRAY + 2) { throw new IllegalArgumentException( "Invalid binary data: Expected array with 2 elements, but was: 0x" + toHex(arrayByte)); } return new JodaBeanStandardBinReader(settings, input).read(declaredType); case 2: if (arrayByte != MIN_FIX_ARRAY + 4) { throw new IllegalArgumentException( "Invalid binary data: Expected array with 4 elements, but was: 0x" + toHex(arrayByte)); } return new JodaBeanReferencingBinReader(settings, input).read(declaredType); case 3: if (arrayByte != MIN_FIX_ARRAY + 3) { throw new IllegalArgumentException( "Invalid binary data: Expected array with 3 elements, but was: 0x" + toHex(arrayByte)); } return new JodaBeanPackedBinReader(settings, input).read(declaredType); default: throw new IllegalArgumentException( "Invalid binary data: Expected version 1, 2 or 3, but was: 0x" + toHex(versionByte)); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanBinWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import static org.joda.beans.ser.bin.JodaBeanBinFormat.REFERENCING; import static org.joda.beans.ser.bin.JodaBeanBinFormat.STANDARD; import java.io.IOException; import java.io.OutputStream; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.LinkedByteArrayOutputStream; /** * Provides the ability for a Joda-Bean to be written to a binary format. *

* This class is immutable and may be used from multiple threads. *

* See {@link JodaBeanBinFormat} for details on each file format. */ public class JodaBeanBinWriter { /** * Settings. */ private final JodaBeanSer settings; /** * The format. */ private final JodaBeanBinFormat format; //----------------------------------------------------------------------- /** * Creates an instance. * * @param settings the settings to use, not null */ public JodaBeanBinWriter(JodaBeanSer settings) { this(settings, STANDARD); } /** * Creates an instance. * * @param settings the settings to use, not null * @param referencing whether to use referencing * @deprecated Use the format instead of the boolean flag */ @Deprecated public JodaBeanBinWriter(JodaBeanSer settings, boolean referencing) { this.settings = Objects.requireNonNull(settings, "settings must not be null"); this.format = referencing ? REFERENCING : STANDARD; } /** * Creates an instance. * * @param settings the settings to use, not null * @param format the format, not null * @since 3.0.0 */ public JodaBeanBinWriter(JodaBeanSer settings, JodaBeanBinFormat format) { this.settings = Objects.requireNonNull(settings, "settings must not be null"); this.format = Objects.requireNonNull(format, "format must not be null"); } //----------------------------------------------------------------------- /** * Writes the bean to an array of bytes. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @return the binary data, not null */ public byte[] write(Bean bean) { return write(bean, true); } /** * Writes the bean to an array of bytes. * * @param bean the bean to output, not null * @param rootType true to output the root type * @return the binary data, not null */ public byte[] write(Bean bean, boolean rootType) { var baos = new LinkedByteArrayOutputStream(); try { write(bean, rootType, baos); } catch (IOException ex) { throw new IllegalStateException(ex); } return baos.toByteArray(); } /** * Writes the bean to the {@code OutputStream}. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @param output the output stream, not null * @throws IOException if an error occurs */ public void write(Bean bean, OutputStream output) throws IOException { write(bean, true, output); } /** * Writes the bean to the {@code OutputStream}. * * @param bean the bean to output, not null * @param includeRootType true to output the root type * @param output the output stream, not null * @throws IOException if an error occurs */ public void write(Bean bean, boolean includeRootType, OutputStream output) throws IOException { Objects.requireNonNull(bean, "bean must not be null"); Objects.requireNonNull(output, "output must not be null"); switch (format) { case STANDARD -> new JodaBeanStandardBinWriter(settings, output).write(bean, includeRootType); case REFERENCING -> new JodaBeanReferencingBinWriter(settings, output).write(bean); case PACKED -> new JodaBeanPackedBinWriter(settings, output).write(bean, includeRootType); default -> throw new IllegalArgumentException("Invalid bin format, must be Standard, Referencing or Packed"); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanPackedBinReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataInputStream; import java.io.IOException; import java.lang.reflect.Array; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.joda.beans.Bean; import org.joda.beans.MetaProperty; import org.joda.beans.ResolvedType; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTypeMapper; import org.joda.collect.grid.DenseGrid; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableGrid; import org.joda.collect.grid.SparseGrid; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.BiMap; import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashBiMap; import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.SetMultimap; import com.google.common.collect.SortedMultiset; import com.google.common.collect.Table; import com.google.common.collect.TreeMultiset; /** * Reads the Joda-Bean BeanPack binary format with strings deduplicated by reference. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ final class JodaBeanPackedBinReader extends BeanPack { /** * The resolved type for {@code Map}. */ private static final ResolvedType MAP_TYPE = ResolvedType.ofFlat(Map.class, Object.class, Object.class); /** * The resolved type for {@code List}. */ private static final ResolvedType LIST_TYPE = ResolvedType.ofFlat(List.class, Object.class); // why is there an ugly ClassValue setup here? // because this is O(1) whereas switch with pattern match which is O(n) private static final ClassValue LOOKUP = new ClassValue<>() { @Override protected BinHandler computeValue(Class type) { return BaseBinHandlers.INSTANCE.createHandler(type); } }; /** * Map of array types. */ private static final Map> ARRAY_TYPE_NAME_MAP = new HashMap<>(); static { ARRAY_TYPE_NAME_MAP.put("Object[]", Object[].class); ARRAY_TYPE_NAME_MAP.put("String[]", String[].class); ARRAY_TYPE_NAME_MAP.put("boolean[]", boolean[].class); ARRAY_TYPE_NAME_MAP.put("char[]", char[].class); ARRAY_TYPE_NAME_MAP.put("byte[]", byte[].class); ARRAY_TYPE_NAME_MAP.put("short[]", short[].class); ARRAY_TYPE_NAME_MAP.put("int[]", int[].class); ARRAY_TYPE_NAME_MAP.put("long[]", long[].class); ARRAY_TYPE_NAME_MAP.put("float[]", float[].class); ARRAY_TYPE_NAME_MAP.put("double[]", double[].class); } /** * Settings. */ final JodaBeanSer settings; // CSIGNORE /** * The reader. */ final DataInputStream input; // CSIGNORE /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map> knownTypes = new HashMap<>(); /** * The type definitions. */ private final List typeDefinitions = new ArrayList<>(); /** * The bean definitions. */ private final Map, List>> beanDefinitions = new IdentityHashMap<>(); /** * The value definitions. */ private final List valueDefinitions = new ArrayList<>(); //----------------------------------------------------------------------- // creates an instance JodaBeanPackedBinReader(JodaBeanSer settings, DataInputStream input) { this.settings = settings; this.input = input; } //----------------------------------------------------------------------- // reads the input stream where the array and version bytes have been read already T read(Class rootType) { try { try { return parseRemaining(rootType); } finally { input.close(); } } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } T parseRemaining(Class declaredType) throws Exception { // the array and version has already been read basePackage = acceptStringOrNull(); var parsed = parseObject(ResolvedType.from(declaredType)); return declaredType.cast(parsed); } //------------------------------------------------------------------------- // parses an object, determining how to parse based on the input data Object parseObject(ResolvedType declaredType) throws IOException { var typeByte = input.readByte(); // parse the type code return switch (typeByte) { case MIN_FIX_MAP -> parseMap(0, declaredType); case MIN_FIX_MAP + 1 -> parseMap(1, declaredType); case MIN_FIX_MAP + 2 -> parseMap(2, declaredType); case MIN_FIX_MAP + 3 -> parseMap(3, declaredType); case MIN_FIX_MAP + 4 -> parseMap(4, declaredType); case MIN_FIX_MAP + 5 -> parseMap(5, declaredType); case MIN_FIX_MAP + 6 -> parseMap(6, declaredType); case MIN_FIX_MAP + 7 -> parseMap(7, declaredType); case MIN_FIX_MAP + 8 -> parseMap(8, declaredType); case MIN_FIX_MAP + 9 -> parseMap(9, declaredType); case MIN_FIX_MAP + 10 -> parseMap(10, declaredType); case MIN_FIX_MAP + 11 -> parseMap(11, declaredType); case MIN_FIX_MAP + 12 -> parseMap(12, declaredType); case MAP_8 -> parseMap(input.readUnsignedByte(), declaredType); case MAP_16 -> parseMap(input.readUnsignedShort(), declaredType); case MAP_32 -> parseMap(input.readInt(), declaredType); case MIN_FIX_ARRAY -> parseArray(0, declaredType); case MIN_FIX_ARRAY + 1 -> parseArray(1, declaredType); case MIN_FIX_ARRAY + 2 -> parseArray(2, declaredType); case MIN_FIX_ARRAY + 3 -> parseArray(3, declaredType); case MIN_FIX_ARRAY + 4 -> parseArray(4, declaredType); case MIN_FIX_ARRAY + 5 -> parseArray(5, declaredType); case MIN_FIX_ARRAY + 6 -> parseArray(6, declaredType); case MIN_FIX_ARRAY + 7 -> parseArray(7, declaredType); case MIN_FIX_ARRAY + 8 -> parseArray(8, declaredType); case MIN_FIX_ARRAY + 9 -> parseArray(9, declaredType); case MIN_FIX_ARRAY + 10 -> parseArray(10, declaredType); case MIN_FIX_ARRAY + 11 -> parseArray(11, declaredType); case MIN_FIX_ARRAY + 12 -> parseArray(12, declaredType); case ARRAY_8 -> parseArray(input.readUnsignedByte(), declaredType); case ARRAY_16 -> parseArray(input.readUnsignedShort(), declaredType); case ARRAY_32 -> parseArray(input.readInt(), declaredType); case STR_8 -> parseString(input.readUnsignedByte(), declaredType); case STR_16 -> parseString(input.readUnsignedShort(), declaredType); case STR_32 -> parseString(input.readInt(), declaredType); case NULL -> null; case FALSE -> false; case TRUE -> true; case UNUSED -> parseUnknown(); case FLOAT_32 -> input.readFloat(); case DOUBLE_INT_8 -> (double) input.readByte(); case DOUBLE_64 -> input.readDouble(); case CHAR_16 -> input.readChar(); case BYTE_8 -> parseByte(input.readByte(), declaredType); case SHORT_16 -> parseShort(input.readShort(), declaredType); case INT_16 -> parseInt(input.readShort(), declaredType); case INT_32 -> parseInt(input.readInt(), declaredType); case LONG_8 -> parseLong(input.readByte(), declaredType); case LONG_16 -> parseLong(input.readShort(), declaredType); case LONG_32 -> parseLong(input.readInt(), declaredType); case LONG_64 -> parseLong(input.readLong(), declaredType); case DATE_PACKED -> parseDatePacked(); case DATE -> parseDate(); case TIME -> parseTime(); case INSTANT -> parseInstant(); case DURATION -> parseDuration(); case BIN_8 -> parseByteArray(input.readUnsignedByte()); case BIN_16 -> parseByteArray(input.readUnsignedShort()); case BIN_32 -> parseByteArray(input.readInt()); case DOUBLE_ARRAY_8 -> parseDoubleArray(input.readUnsignedByte()); case DOUBLE_ARRAY_16 -> parseDoubleArray(input.readUnsignedShort()); case DOUBLE_ARRAY_32 -> parseDoubleArray(input.readInt()); case TYPE_DEFN_8 -> parseTypeDefinition(input.readUnsignedByte()); case TYPE_DEFN_16 -> parseTypeDefinition(input.readUnsignedShort()); case TYPE_REF_8 -> parseTypeRef(input.readByte(), declaredType); case TYPE_REF_16 -> parseTypeRef(input.readUnsignedShort(), declaredType); case BEAN_DEFN -> parseBeanDefinition(input.readUnsignedByte(), declaredType); case VALUE_DEFN -> parseValueDefinition(declaredType); case VALUE_REF_8 -> parseValueRef(input.readUnsignedByte(), declaredType); case VALUE_REF_16 -> parseValueRef(input.readUnsignedShort(), declaredType); case VALUE_REF_24 -> parseValueRef((input.readUnsignedByte() << 16) + input.readUnsignedShort(), declaredType); default -> typeByte < MIN_FIX_INT ? parseString(typeByte - MIN_FIX_STR, declaredType) : parseInt(typeByte, declaredType); }; } //------------------------------------------------------------------------- // parse a BeanPack map private Object parseMap(int size, ResolvedType declaredType) throws IOException { var rawType = declaredType.getRawType(); if (Bean.class.isAssignableFrom(rawType)) { return parseMapAsBean(size, rawType, false); } else { return parseViaHandler(size, rawType == Object.class ? MAP_TYPE : declaredType); } } // parse a BeanPack array private Object parseArray(int size, ResolvedType declaredType) throws IOException { var rawType = declaredType.getRawType(); if (Bean.class.isAssignableFrom(rawType)) { return parseArrayAsBean(size, rawType); } else { return parseViaHandler(size, rawType == Object.class ? LIST_TYPE : declaredType); } } // parse a BeanPack map as a Map/Array private Object parseViaHandler(int size, ResolvedType declaredType) throws IOException { var handler = LOOKUP.get(declaredType.getRawType()); return handler.handle(this, declaredType, size); } //------------------------------------------------------------------------- // parse a BeanPack string private Object parseString(int strLen, ResolvedType declaredType) throws IOException { var str = acceptStringBytes(strLen); return interpretString(str, declaredType); } private Object interpretString(String str, ResolvedType declaredType) { if (declaredType.getRawType().isAssignableFrom(String.class)) { return str; } else { // Joda-Convert return settings.getConverter().convertFromString(declaredType.getRawType(), str); } } private Object parseUnknown() { throw new IllegalArgumentException("Invalid binary data: Unknown type byte"); } //------------------------------------------------------------------------- // parse the type name, validate it, store it in the type cache and parse the actual value private Object parseTypeDefinition(int size) throws IOException { // manually parse, as separate from the value definition var bytes = new byte[size]; input.readFully(bytes); var typeName = new String(bytes, UTF_8); // interpret the type, which is always a Class (not a ResolvedType) Class decodedType = decodeTypeName(typeName); var effectiveType = ResolvedType.of(decodedType); typeDefinitions.add(effectiveType); return parseObject(effectiveType); } private Class decodeTypeName(String typeName) { try { if (typeName.endsWith("[]")) { return decodeArrayTypeName(typeName); } else { return settings.getDeserializers().decodeType(typeName, settings, basePackage, knownTypes, Object.class); } } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } } // finds the array type from a string like int[] or Foo[][] private Class decodeArrayTypeName(String typeName) throws ClassNotFoundException { var type = ARRAY_TYPE_NAME_MAP.get(typeName); if (type != null) { return type; } var clsStr = typeName.substring(0, typeName.length() - 2); if (clsStr.endsWith("[]")) { return decodeArrayTypeName(clsStr).arrayType(); } return SerTypeMapper.decodeType(clsStr, settings, null, knownTypes).arrayType(); } // parse the int reference, negative for type codes and positive for user types private Object parseTypeRef(int ref, ResolvedType declaredType) throws IOException { if (ref < 0) { var rawEffectiveType = BaseBinHandlers.INSTANCE.classForTypeCode(ref); var effectiveType = ResolvedType.of(rawEffectiveType); return parseObject(effectiveType); } else { var effectiveType = typeDefinitions.get(ref); return parseObject(effectiveType); } } // parse the actual bean, passing down a flag so that the meta-properties are stored in the bean cache private Object parseBeanDefinition(int propertyCount, ResolvedType declaredType) throws IOException { // when written, the bean definition is always preceded by a type definition/ref var beanType = declaredType.getRawType(); if (!Bean.class.isAssignableFrom(beanType)) { throw new IllegalArgumentException("Invalid binary data: Expected bean, but found " + declaredType); } // parse the meta-property names first var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); var metaProperties = new ArrayList>(propertyCount); for (var i = 0; i < propertyCount; i++) { var propName = acceptString(); var metaProp = deser.findMetaProperty(beanType, metaBean, propName); if (metaProp == null || !settings.isSerialized(metaProp)) { metaProperties.add(null); // message contains a property that is no longer in the bean } else { metaProperties.add(metaProp); } } beanDefinitions.put(beanType, metaProperties); // now the meta-property names are stored, we can parse the bean values var propName = ""; try { var builder = deser.createBuilder(beanType, metaBean); for (var i = 0; i < propertyCount; i++) { var metaProp = metaProperties.get(i); if (metaProp == null) { propName = ""; skipObject(); } else { propName = metaProp.name(); var value = parseObject(metaProp.propertyResolvedType(beanType)); deser.setValue(builder, metaProp, value); } } propName = ""; return deser.build(beanType, builder); } catch (IOException ex) { throw ex; } catch (Exception ex) { throw invalidBean(beanType, propName, ex); } } // parse the actual value, store it in the value cache, and return the value private Object parseValueDefinition(ResolvedType declaredType) throws IOException { var obj = parseObject(declaredType); valueDefinitions.add(obj); return obj; } // obtain the value reference, query the value cache, and return the value private Object parseValueRef(int ref, ResolvedType declaredType) throws IOException { var value = valueDefinitions.get(ref); if (value instanceof String str) { return interpretString(str, declaredType); } else if (value != null) { return value; } else { throw new IllegalArgumentException("Invalid binary data: Referenced value not found: ref " + ref); } } //------------------------------------------------------------------------- // parse a BeanPack map that has been identified as a bean private Object parseMapAsBean(int mapSize, Class beanType, boolean isDefinition) throws IOException { var propName = ""; try { var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); var builder = deser.createBuilder(beanType, metaBean); var metaProperties = new ArrayList>(mapSize); for (var i = 0; i < mapSize; i++) { propName = acceptString(); var metaProp = deser.findMetaProperty(beanType, metaBean, propName); if (metaProp == null || metaProp.style().isDerived()) { skipObject(); metaProperties.add(null); } else { var value = parseObject(metaProp.propertyResolvedType(beanType)); deser.setValue(builder, metaProp, value); metaProperties.add(metaProp); } } if (isDefinition) { beanDefinitions.put(beanType, metaProperties); } propName = ""; return deser.build(beanType, builder); } catch (IOException ex) { throw ex; } catch (Exception ex) { throw invalidBean(beanType, propName, ex); } } // parse a BeanPack array that has been identified as a bean (by reference) private Object parseArrayAsBean(int arraySize, Class beanType) throws IOException { var propName = ""; try { var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); var builder = deser.createBuilder(beanType, metaBean); var metaProperties = beanDefinitions.get(beanType); if (metaProperties == null) { throw invalidBeanRef(beanType); } if (metaProperties.size() != arraySize) { throw invalidBeanRefSize(beanType); } for (var i = 0; i < arraySize; i++) { var metaProp = metaProperties.get(i); if (metaProp == null) { propName = ""; skipObject(); } else { propName = metaProp.name(); var value = parseObject(metaProp.propertyResolvedType(beanType)); deser.setValue(builder, metaProp, value); } } propName = ""; return deser.build(beanType, builder); } catch (IOException ex) { throw ex; } catch (Exception ex) { throw invalidBean(beanType, propName, ex); } } private IllegalArgumentException invalidBeanRef(Class beanType) { return new IllegalArgumentException( "Invalid binary data: Referenced bean not found: " + beanType.getName()); } private IllegalArgumentException invalidBeanRefSize(Class beanType) { return new IllegalArgumentException( "Invalid binary data: Referenced bean had different number of properties: " + beanType.getName()); } private RuntimeException invalidBean(Class beanType, String propName, Exception ex) { return new RuntimeException("Error parsing bean: " + beanType.getName() + "::" + propName + ", " + ex.getMessage(), ex); } //------------------------------------------------------------------------- // parse a byte, allowing conversion to other number types private Object parseByte(byte value, ResolvedType declaredType) { var desiredType = declaredType.getRawType(); if (desiredType == byte.class || desiredType == Byte.class) { return value; } else { return parseLongWithConversion(value, value, desiredType); } } // parse a short, allowing conversion to other number types private Object parseShort(short value, ResolvedType declaredType) { var desiredType = declaredType.getRawType(); if (desiredType == short.class || desiredType == Short.class) { return value; } else { return parseLongWithConversion(value, value, desiredType); } } // parse an int, allowing conversion to other number types private Object parseInt(int value, ResolvedType declaredType) { var desiredType = declaredType.getRawType(); if (desiredType == int.class || desiredType == Integer.class) { return value; } else { return parseLongWithConversion(value, value, desiredType); } } // parse a long, allowing conversion to other number types private Object parseLong(long value, ResolvedType declaredType) { var desiredType = declaredType.getRawType(); if (desiredType == long.class || desiredType == Long.class) { return value; } else { return parseLongWithConversion(value, value, desiredType); } } // convert the value that we have been given to the desired type private Object parseLongWithConversion(long value, Number defaultValue, Class desiredType) { if (desiredType == Object.class || desiredType == Number.class) { return defaultValue; } else if (desiredType == Long.class || desiredType == long.class) { return value; } else if (desiredType == Integer.class || desiredType == int.class) { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected int, but was " + value); } return Integer.valueOf((int) value); } else if (desiredType == Double.class || desiredType == double.class) { return Double.valueOf(value); } else if (desiredType == Float.class || desiredType == float.class) { return Float.valueOf(value); } else if (desiredType == Short.class || desiredType == short.class) { if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected short, but was " + value); } return Short.valueOf((short) value); } else if (desiredType == Byte.class || desiredType == byte.class) { if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { throw new IllegalArgumentException("Invalid binary data: Expected byte, but was " + value); } return Byte.valueOf((byte) value); } return defaultValue; // will probably throw an exception in the calling code } //------------------------------------------------------------------------- private LocalDate parseDatePacked() throws IOException { var packed = input.readUnsignedShort(); var dom = packed & 31; var ym = packed >> 5; return LocalDate.of((ym / 12) + 2000, (ym % 12) + 1, dom); } private LocalDate parseDate() throws IOException { var upper = input.readInt(); var lower = input.readUnsignedByte(); var year = upper >> 1; var month = ((upper & 1) << 3) + (lower >>> 5); var dom = lower & 31; return LocalDate.of(year, month, dom); } private LocalTime parseTime() throws IOException { var upper = input.readShort(); var lower = Integer.toUnsignedLong(input.readInt()); var nod = ((long) upper << 32) + lower; return LocalTime.ofNanoOfDay(nod); } private Instant parseInstant() throws IOException { var second = input.readLong(); var nanos = input.readInt(); return Instant.ofEpochSecond(second, nanos); } private Duration parseDuration() throws IOException { var seconds = input.readLong(); var nanos = input.readInt(); return Duration.ofSeconds(seconds, nanos); } //----------------------------------------------------------------------- private byte[] parseByteArray(int size) throws IOException { var bytes = new byte[size]; input.readFully(bytes); return bytes; } private double[] parseDoubleArray(int size) throws IOException { var values = new double[size]; for (int i = 0; i < size; i++) { values[i] = input.readDouble(); } return values; } //------------------------------------------------------------------------- private void skipObject() throws IOException { // The only things we care about here are type definitions, bean definition and value definitions. // Type definitions contain the class name, allowing normal parsing to resume. // Bean definitions are always written preceded by a class name, which is sufficient to read the definition. // Value definitions are always written preceded by a class name, which is sufficient to read the definition. // // Each bean acts as a point of separation, where the resolved type is deliberately dropped. // As such, a meta-property holding a generic bean will only use the raw form of the bean for typing. // // A collection is held either in a property, in which case the type is obtained via the property // or it is held in Object/Serializable, in which case no type information is available. // No collection-like class has a generified superclass that is not handled, thus there are no gaps in the type knowledge. parseObject(ResolvedType.OBJECT); } private String acceptString() throws IOException { return acceptString(input.readByte()); } private String acceptStringOrNull() throws IOException { var typeByte = input.readByte(); return typeByte == NULL ? null : acceptString(typeByte); } private String acceptString(int typeByte) throws IOException { int size; if (typeByte == VALUE_REF_8) { return parseValueRef(input.readUnsignedByte(), ResolvedType.STRING).toString(); } else if (typeByte == VALUE_REF_16) { return parseValueRef(input.readUnsignedShort(), ResolvedType.STRING).toString(); } else if (typeByte == VALUE_REF_24) { return parseValueRef(input.readUnsignedByte() << 16 + input.readUnsignedShort(), ResolvedType.STRING).toString(); } else if (typeByte >= MIN_FIX_STR && typeByte <= MAX_FIX_STR) { size = typeByte - MIN_FIX_STR; } else if (typeByte == STR_8) { size = input.readUnsignedByte(); } else if (typeByte == STR_16) { size = input.readUnsignedShort(); } else if (typeByte == STR_32) { size = input.readInt(); } else { throw invalidBinaryData("string", typeByte); } return acceptStringBytes(size); } private String acceptStringBytes(int size) throws IOException { var bytes = new byte[size]; input.readFully(bytes); // inline common ASCII case for much better performance var chars = new char[size]; for (var i = 0; i < size; i++) { var b = bytes[i]; if (b >= 0) { chars[i] = (char) b; } else { return new String(bytes, UTF_8); } } var str = new String(chars); if (str.length() >= JodaBeanPackedBinWriter.MIN_LENGTH_STR_VALUE) { valueDefinitions.add(str); } return str; } private int acceptInt() throws IOException { var typeByte = input.readByte(); if (typeByte >= MIN_FIX_INT && typeByte <= MAX_FIX_INT) { return typeByte; } return switch (typeByte) { case INT_16 -> input.readShort(); case INT_32 -> input.readInt(); default -> throw invalidBinaryData("int", typeByte); }; } private int acceptMap() throws IOException { var typeByte = input.readByte(); if (typeByte >= MIN_FIX_MAP && typeByte <= MAX_FIX_MAP) { return typeByte - MIN_FIX_MAP; } return switch (typeByte) { case MAP_8 -> input.readByte(); case MAP_16 -> input.readShort(); case MAP_32 -> input.readInt(); default -> throw invalidBinaryData("map", typeByte); }; } private int acceptArray() throws IOException { var typeByte = input.readByte(); if (typeByte >= MIN_FIX_ARRAY && typeByte <= MAX_FIX_ARRAY) { return typeByte - MIN_FIX_ARRAY; } return switch (typeByte) { case ARRAY_8 -> input.readByte(); case ARRAY_16 -> input.readShort(); case ARRAY_32 -> input.readInt(); default -> throw invalidBinaryData("array", typeByte); }; } private IllegalArgumentException invalidBinaryData(String expected, int actualByte) { return new IllegalArgumentException( "Invalid binary data: Expected " + expected + ", but was: 0x" + toHex(actualByte)); } //------------------------------------------------------------------------- private static interface BinHandler { public abstract Object handle( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException; } //------------------------------------------------------------------------- private static sealed class BaseBinHandlers { // an instance loaded dependent on the classpath private static final BaseBinHandlers INSTANCE = getInstance(); private static final BaseBinHandlers getInstance() { try { ImmutableGrid.of(); // check if class is available return new CollectBinHandlers(); } catch (Exception | LinkageError ex) { try { ImmutableMultiset.of(); // check if class is available return new GuavaBinHandlers(); } catch (Exception | LinkageError ex2) { return new BaseBinHandlers(); } } } BinHandler createHandler(Class type) { if (SortedSet.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseCollection(reader, declType, size, new TreeSet<>()); } if (Set.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseCollection(reader, declType, size, LinkedHashSet.newLinkedHashSet(size)); } if (Iterable.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseCollection(reader, declType, size, new ArrayList<>(size)); } if (SortedMap.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMap(reader, declType, size, new TreeMap<>()); } if (Map.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMap(reader, declType, size, LinkedHashMap.newLinkedHashMap(size)); } if (Optional.class.isAssignableFrom(type)) { return BaseBinHandlers::parseOptional; } if (type.isArray()) { return BaseBinHandlers::parseArray; } throw new IllegalArgumentException("Invalid binary data: Unknown collection: " + type.getName()); } Class classForTypeCode(int typeCode) { return switch (typeCode) { case TYPE_CODE_LIST -> List.class; case TYPE_CODE_SET -> Set.class; case TYPE_CODE_MAP -> Map.class; case TYPE_CODE_OPTIONAL -> Optional.class; case TYPE_CODE_OBJECT_ARRAY -> Object[].class; case TYPE_CODE_STRING_ARRAY -> String[].class; default -> throw new IllegalArgumentException("Invalid binary data: Unknown type code: " + typeCode); }; } // collection - parsed from a BeanPack array private static Collection parseCollection( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size, Collection collection) throws IOException { var itemType = declaredType.getArgumentOrDefault(0); for (var i = 0; i < size; i++) { collection.add(reader.parseObject(itemType)); } return collection; } // map - parsed from a BeanPack map static Map parseMap( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size, Map map) throws IOException { var keyType = declaredType.getArgumentOrDefault(0); var valueType = declaredType.getArgumentOrDefault(1); for (var i = 0; i < size; i++) { var key = reader.parseObject(keyType); var value = reader.parseObject(valueType); map.put(key, value); } return map; } // optional - parsed from a BeanPack array, size 0 or 1 private static Optional parseOptional( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException { return switch (size) { case 0 -> Optional.empty(); case 1 -> { var itemType = declaredType.getArgumentOrDefault(0); var value = reader.parseObject(itemType); yield Optional.ofNullable(value); } default -> throw new IllegalArgumentException( "Invalid binary data: Optional must be an array of size zero or one, but was " + size); }; } // array - parsed from a BeanPack array private static Object parseArray( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException { var componentType = declaredType.toComponentType(); var array = Array.newInstance(componentType.getRawType(), size); for (var i = 0; i < size; i++) { Array.set(array, i, reader.parseObject(componentType)); } return array; } } //------------------------------------------------------------------------- private static sealed class GuavaBinHandlers extends BaseBinHandlers { @Override BinHandler createHandler(Class type) { if (SortedMultiset.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMultiset(reader, declType, size, TreeMultiset.create()); } if (Multiset.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMultiset(reader, declType, size, HashMultiset.create()); } if (SetMultimap.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMultimap(reader, declType, size, HashMultimap.create()); } if (Multimap.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMultimap(reader, declType, size, ArrayListMultimap.create()); } if (Table.class.isAssignableFrom(type)) { return GuavaBinHandlers::parseTable; } if (BiMap.class.isAssignableFrom(type)) { return (reader, declType, size) -> parseMap(reader, declType, size, HashBiMap.create()); } if (com.google.common.base.Optional.class.isAssignableFrom(type)) { return GuavaBinHandlers::parseOptional; } // these are optimizations, so don't match subtypes like ImmutableSortedSet or ImmutableSortedMap if (ImmutableSet.class == type) { return (reader, declType, size) -> parseImmutableCollection( reader, declType, size, ImmutableSet.builderWithExpectedSize(size)); } if (ImmutableList.class == type) { return (reader, declType, size) -> parseImmutableCollection( reader, declType, size, ImmutableList.builderWithExpectedSize(size)); } if (ImmutableMap.class == type) { return (reader, declType, size) -> parseImmutableMap(reader, declType, size); } return super.createHandler(type); } @Override Class classForTypeCode(int typeCode) { return switch (typeCode) { case TYPE_CODE_MULTISET -> Multiset.class; case TYPE_CODE_LIST_MULTIMAP -> ListMultimap.class; case TYPE_CODE_SET_MULTIMAP -> SetMultimap.class; case TYPE_CODE_TABLE -> Table.class; case TYPE_CODE_BIMAP -> BiMap.class; case TYPE_CODE_GUAVA_OPTIONAL -> com.google.common.base.Optional.class; default -> super.classForTypeCode(typeCode); }; } // multiset - parsed from a BeanPack map of value to count @SuppressWarnings({"rawtypes", "unchecked"}) private static Multiset parseMultiset( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size, Multiset mset) throws IOException { var itemType = declaredType.getArgumentOrDefault(0); for (var i = 0; i < size; i++) { var item = reader.parseObject(itemType); var count = reader.acceptInt(); mset.add(item, count); } return mset; } // multimap - parsed from a BeanPack map of key to array of values private static Multimap parseMultimap( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size, Multimap mmap) throws IOException { var keyType = declaredType.getArgumentOrDefault(0); var valueType = declaredType.getArgumentOrDefault(1); for (var i = 0; i < size; i++) { var key = reader.parseObject(keyType); var valueSize = reader.acceptArray(); for (var j = 0; j < valueSize; j++) { var value = reader.parseObject(valueType); mmap.put(key, value); } } return mmap; } // table - parsed from a BeanPack map of row to map of column to value private static Table parseTable( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException { var rowType = declaredType.getArgumentOrDefault(0); var columnType = declaredType.getArgumentOrDefault(1); var valueType = declaredType.getArgumentOrDefault(2); var table = HashBasedTable.create(); for (var i = 0; i < size; i++) { var row = reader.parseObject(rowType); var colSize = reader.acceptMap(); for (var j = 0; j < colSize; j++) { var column = reader.parseObject(columnType); var value = reader.parseObject(valueType); table.put(row, column, value); } } return table; } // optional - parsed from a BeanPack array, size 0 or 1 private static com.google.common.base.Optional parseOptional( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException { return switch (size) { case 0 -> com.google.common.base.Optional.absent(); case 1 -> { var itemType = declaredType.getArgumentOrDefault(0); var value = reader.parseObject(itemType); yield com.google.common.base.Optional.fromNullable(value); } default -> throw new IllegalArgumentException( "Invalid binary data: Optional must be an array of size zero or one, but was " + size); }; } // immutable collection - optimizes using builder and expected size private static ImmutableCollection parseImmutableCollection( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size, ImmutableCollection.Builder builder) throws IOException { var itemType = declaredType.getArgumentOrDefault(0); for (var i = 0; i < size; i++) { var item = reader.parseObject(itemType); builder.add(item); } return builder.build(); } // immutable map - optimizes using builder and expected size private static ImmutableMap parseImmutableMap( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException { var builder = ImmutableMap.builderWithExpectedSize(size); var keyType = declaredType.getArgumentOrDefault(0); var valueType = declaredType.getArgumentOrDefault(1); for (var i = 0; i < size; i++) { var key = reader.parseObject(keyType); var value = reader.parseObject(valueType); builder.put(key, value); } return builder.build(); } } //------------------------------------------------------------------------- private static final class CollectBinHandlers extends GuavaBinHandlers { @Override BinHandler createHandler(Class type) { if (Grid.class.isAssignableFrom(type)) { return CollectBinHandlers::parseGrid; } return super.createHandler(type); } @Override Class classForTypeCode(int typeCode) { return switch (typeCode) { case TYPE_CODE_GRID -> Grid.class; default -> super.classForTypeCode(typeCode); }; } // grid private static Grid parseGrid( JodaBeanPackedBinReader reader, ResolvedType declaredType, int size) throws IOException { var valueType = declaredType.getArgumentOrDefault(0); if (size != 3) { throw new IllegalArgumentException( "Invalid binary data: Grid must be an array of size three, but was " + size); } var rowCount = reader.acceptInt(); var colCount = reader.acceptInt(); var arraySize = reader.acceptArray(); if (rowCount < 0) { // dense rowCount = -rowCount; var grid = DenseGrid.create(rowCount, colCount); for (var row = 0; row < rowCount; row++) { for (var col = 0; col < colCount; col++) { var value = reader.parseObject(valueType); if (value != null) { grid.put(row, col, value); } } } return grid; } else { // sparse var grid = SparseGrid.create(rowCount, colCount); for (var i = 0; i < arraySize / 3; i++) { var row = reader.acceptInt(); var col = reader.acceptInt(); var value = reader.parseObject(valueType); if (value != null) { grid.put(row, col, value); } } return grid; } } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanPackedBinWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Array; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.Spliterator; import java.util.stream.StreamSupport; import org.joda.beans.Bean; import org.joda.beans.DynamicBean; import org.joda.beans.MetaProperty; import org.joda.beans.ResolvedType; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.impl.map.MapBean; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTypeMapper; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableGrid; import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.SetMultimap; import com.google.common.collect.Table; /** * Writes the Joda-Bean BeanPack binary format with strings deduplicated by reference. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ final class JodaBeanPackedBinWriter { static final int MIN_LENGTH_STR_VALUE = 3; // why is there an ugly ClassValue setup here? // because this is O(1) whereas switch with pattern match which is O(n) private static final ClassValue> LOOKUP = new ClassValue<>() { @SuppressWarnings("rawtypes") // sneaky use of raw type to allow typed value in each method below @Override protected BinHandler computeValue(Class type) { if (Bean.class.isAssignableFrom(type)) { return (BinHandler) JodaBeanPackedBinWriter::writeBeanMaybeSimple; } // these primitive types are always written and interpretted without a type if (type == String.class) { return (writer, declaredType, propName, value) -> writer.writeString((String) value); } if (type == Integer.class || type == int.class) { return (writer, declaredType, propName, value) -> writer.output.writeInt((Integer) value); } if (type == Long.class || type == long.class) { return (writer, declaredType, propName, value) -> writer.output.writeLong((Long) value); } if (type == Byte.class || type == byte.class) { return (writer, declaredType, propName, value) -> writer.output.writeByte((Byte) value); } if (type == Short.class || type == short.class) { return (writer, declaredType, propName, value) -> writer.output.writeShort((Short) value); } if (type == Character.class || type == char.class) { return (writer, declaredType, propName, value) -> writer.output.writeChar((Character) value); } if (type == Double.class || type == double.class) { return (writer, declaredType, propName, value) -> writer.output.writeDouble((Double) value); } if (type == Float.class || type == float.class) { return (writer, declaredType, propName, value) -> writer.output.writeFloat((Float) value); } if (type == Boolean.class || type == boolean.class) { return (writer, declaredType, propName, value) -> writer.output.writeBoolean((Boolean) value); } if (type == LocalDate.class) { return (writer, declaredType, propName, value) -> writer.output.writeDate((LocalDate) value); } if (type == LocalTime.class) { return (writer, declaredType, propName, value) -> writer.output.writeTime((LocalTime) value); } if (type == Instant.class) { return (writer, declaredType, propName, value) -> writer.output.writeInstant((Instant) value); } if (type == Duration.class) { return (writer, declaredType, propName, value) -> writer.output.writeDuration((Duration) value); } return BaseBinHandlers.INSTANCE.createHandler(type); } }; /** * The settings to use. */ private final JodaBeanSer settings; /** * The outputter. */ private final BeanPackOutput output; /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map, String> knownTypes = new IdentityHashMap<>(); /** * The type definitions that have been output. */ private int typeDefinitionIndex; /** * The type definitions that have been output. */ private final Map, Integer> typeDefinitions = new IdentityHashMap<>(); /** * The bean definitions. */ private final Map, List>> beanDefinitions = new IdentityHashMap<>(); /** * The type definitions that have been output. */ private int valueDefinitionIndex; /** * The value definitions that have been output. */ private final Map valueDefinitions = new HashMap<>(); /** * Creates an instance. * * @param settings the settings to use, not null * @param out the output stream, not null */ JodaBeanPackedBinWriter(JodaBeanSer settings, OutputStream out) { this.settings = settings; this.output = new BeanPackOutput(out); } //------------------------------------------------------------------------- /** * Writes the bean to the {@code OutputStream}. * * @param bean the bean to output, not null * @param includeRootType whether to include the root type * @throws IOException if an error occurs */ void write(Bean bean, boolean includeRootType) throws IOException { var beanClass = bean.getClass(); // these first two bytes in BeanPack are compatible with MsgPack! output.writeArrayHeader(3); output.writeInt(3); // version 3 if (includeRootType && beanClass != FlexiBean.class && beanClass != MapBean.class && settings.isShortTypes()) { basePackage = beanClass.getPackage().getName() + '.'; SerTypeMapper.encodeType(beanClass, settings, basePackage, knownTypes); writeString(basePackage); } else { basePackage = null; output.writeNull(); } // root always outputs the bean, not Joda-Convert form writeBean(ResolvedType.of(beanClass), bean, includeRootType); if (typeDefinitionIndex > 0xFFFF) { throw new IllegalArgumentException("Invalid bindary data: Too many type references"); } if (valueDefinitionIndex > 0xFFFFFF) { throw new IllegalArgumentException("Invalid bindary data: Too many value references"); } } //----------------------------------------------------------------------- // writes an object, by determining the runtime type private void writeObject(ResolvedType declaredType, String propertyName, Object value) throws IOException { if (value == null) { output.writeNull(); } else { var handler = LOOKUP.get(value.getClass()); handler.handle(this, declaredType, propertyName, value); } } //------------------------------------------------------------------------- // writes a bean, favouring output as a Joda-Convert type private void writeBeanMaybeSimple(ResolvedType declaredType, String propertyName, Bean bean) throws IOException { // check for Joda-Convert cannot be in ClassValue as it relies on the settings // cannot call valueDefinitions.get(value) here, as hashCode() of a random bean may be very expensive if (settings.getConverter().isConvertible(bean.getClass())) { writeSimple(propertyName, bean); } else if (settings.getBeanValueClasses().contains(bean.getClass())) { writeCachedBean(bean); } else { writeBean(declaredType, bean, true); } } // writes a bean, where the bean is a value that can be cached private void writeCachedBean(Bean bean) throws IOException { // note that the declared type is not used to refine the output, creating separation of types in the binary form var ref = valueDefinitions.get(bean); if (ref == null) { // always write the type, as it could be read while skipping where the type is not known output.writeValueDefinitionHeader(); writeTypeNameOrReference(bean.getClass()); var beanClass = bean.getClass(); var metaProperties = beanDefinitions.get(beanClass); if (metaProperties == null) { writeBeanWithDefinition(bean); } else { writeBeanValues(bean, metaProperties); } valueDefinitions.put(bean, valueDefinitionIndex++); } else { output.writeValueReference(ref); } } // writes a bean, with meta type information if necessary private void writeBean(ResolvedType declaredType, Bean bean, boolean includeRootType) throws IOException { var beanClass = bean.getClass(); var metaProperties = beanDefinitions.get(beanClass); if (metaProperties == null) { if (bean instanceof DynamicBean || !includeRootType) { if (beanClass != declaredType.getRawType()) { writeTypeNameOrReference(beanClass); } writeDynamicBean(bean); } else { // always write the type, as it could be read while skipping where the type is not known writeTypeNameOrReference(beanClass); writeBeanWithDefinition(bean); } } else { if (beanClass != declaredType.getRawType()) { writeTypeNameOrReference(beanClass); } writeBeanValues(bean, metaProperties); } } // writes the dynamic bean as a map of property name to property value, without any type information private void writeDynamicBean(Bean bean) throws IOException { // note that the declared type is not used to refine the output, creating separation of types in the binary form var beanClass = bean.getClass(); var metaBean = bean.metaBean(); var beanMap = new LinkedHashMap, Object>(metaBean.metaPropertyCount()); for (var metaProperty : metaBean.metaPropertyIterable()) { if (settings.isSerialized(metaProperty)) { var value = metaProperty.get(bean); if (value != null) { beanMap.put(metaProperty, value); } } } output.writeMapHeader(beanMap.size()); for (var entry : beanMap.entrySet()) { var metaProperty = entry.getKey(); var value = entry.getValue(); var resolvedType = metaProperty.propertyResolvedType(beanClass); var childPropertyName = metaProperty.name(); if (value != null) { writeString(childPropertyName); writeObject(resolvedType, childPropertyName, value); } } } // writes the bean definition structure private void writeBeanWithDefinition(Bean bean) throws IOException { // note that the declared type is not used to refine the output, creating separation of types in the binary form var metaProperties = findSerializedMetaProperties(bean); if (metaProperties.size() > 255) { writeDynamicBean(bean); } else { var beanClass = bean.getClass(); beanDefinitions.put(beanClass, metaProperties); output.writeBeanDefinitionHeader(metaProperties.size()); for (var metaProperty : metaProperties) { writeString(metaProperty.name()); } for (var metaProperty : metaProperties) { var resolvedType = metaProperty.propertyResolvedType(beanClass); var childPropertyName = metaProperty.name(); var value = metaProperty.get(bean); writeObject(resolvedType, childPropertyName, value); } } } // find the list of meta properties that will be serialized private ArrayList> findSerializedMetaProperties(Bean bean) { var metaBean = bean.metaBean(); var metaProperties = new ArrayList>(metaBean.metaPropertyCount()); for (var metaProperty : metaBean.metaPropertyIterable()) { if (settings.isSerialized(metaProperty)) { metaProperties.add(metaProperty); } } return metaProperties; } // writes the bean values without property names, effectively referring back to the original definition private void writeBeanValues(Bean bean, List> metaProperties) throws IOException { // note that the declared type is not used to refine the output, creating separation of types in the binary form var beanClass = bean.getClass(); output.writeArrayHeader(metaProperties.size()); for (var metaProperty : metaProperties) { if (settings.isSerialized(metaProperty)) { var resolvedType = metaProperty.propertyResolvedType(beanClass); var childPropertyName = metaProperty.name(); var value = metaProperty.get(bean); writeObject(resolvedType, childPropertyName, value); } } } //----------------------------------------------------------------------- // writes a string private void writeString(String str) throws IOException { if (str.length() >= MIN_LENGTH_STR_VALUE) { var ref = valueDefinitions.get(str); if (ref == null) { valueDefinitions.put(str, valueDefinitionIndex++); output.writeString(str); } else { output.writeValueReference(ref); } } else { output.writeString(str); } } // writes a simple type, with meta type information if necessary // this method is never called for primitive types like int/long/LocalDate private void writeSimple(String propertyName, Object value) throws IOException { // note that the declared type is not used to refine the output, creating separation of types in the binary form // write the reference, or call Joda-Convert if first time value is seen var ref = valueDefinitions.get(value); if (ref == null) { // always write the type (by passing OBJECT), as it could be read while skipping where the type is not known output.writeValueDefinitionHeader(); writeJodaConvert(ResolvedType.OBJECT, propertyName, value); valueDefinitions.put(value, valueDefinitionIndex++); } else { output.writeValueReference(ref); } } // writes the object as a String using Joda-Convert private void writeJodaConvert(ResolvedType declaredType, String propertyName, Object value) throws IOException { try { // handle situations where there is no declared type, or there is a subclass of the declared type var effectiveType = value.getClass(); var converter = settings.getConverter().findTypedConverterNoGenerics(effectiveType); if (effectiveType != declaredType.toBoxed().getRawType()) { effectiveType = converter.getEffectiveType(); writeTypeNameOrReference(effectiveType); } var converted = converter.convertToString(value); if (converted == null) { output.writeNull(); return; } writeString(converted); } catch (RuntimeException ex) { throw invalidConversionMsg(propertyName, value, ex); } } private IllegalArgumentException invalidConversionMsg(String propertyName, Object value, RuntimeException ex) { var msg = "Unable to write property '" + propertyName + "', type " + value.getClass().getName() + " could not be converted to a String"; return new IllegalArgumentException(msg, ex); } // writes the type header private final void writeTypeNameOrReference(Class type) throws IOException { var ref = typeDefinitions.get(type); if (ref == null) { var encodedClassName = SerTypeMapper.encodeType(type, settings, basePackage, knownTypes); typeDefinitions.put(type, typeDefinitionIndex++); output.writeTypeName(encodedClassName); } else { output.writeTypeReference(ref); } } //------------------------------------------------------------------------- private static interface BinHandler { public abstract void handle( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, T obj) throws IOException; } //------------------------------------------------------------------------- // handles base JDK collections private static sealed class BaseBinHandlers { // an instance loaded dependent on the classpath private static final BaseBinHandlers INSTANCE = getInstance(); private static final BaseBinHandlers getInstance() { try { ImmutableGrid.of(); // check if class is available return new CollectBinHandlers(); } catch (Exception | LinkageError ex) { try { ImmutableMultiset.of(); // check if class is available return new GuavaBinHandlers(); } catch (Exception | LinkageError ex2) { return new BaseBinHandlers(); } } } // creates the handler, called from ClassValue.computeValue() BinHandler createHandler(Class type) { if (Optional.class.isAssignableFrom(type)) { return (BinHandler>) BaseBinHandlers::writeOptional; } if (type == byte[].class) { return (writer, declaredType, propName, value) -> writer.output.writeBytes((byte[]) value); } if (type == double[].class) { return (writer, declaredType, propName, value) -> writer.output.writeDoubles((double[]) value); } if (type.isArray()) { var componentType = type.getComponentType(); if (componentType.isPrimitive()) { return (BinHandler) BaseBinHandlers::writePrimitiveArray; } else { return (BinHandler) BaseBinHandlers::writeArray; } } if (Map.class.isAssignableFrom(type)) { return (BinHandler>) BaseBinHandlers::writeMap; } if (Collection.class.isAssignableFrom(type)) { return (BinHandler>) BaseBinHandlers::writeCollection; } if (Iterable.class.isAssignableFrom(type)) { return (BinHandler>) BaseBinHandlers::writeIterable; } return (writer, declaredType, propertyName, value) -> writer.writeSimple(propertyName, value); } // writes an optional, with meta type information if necessary private static void writeOptional( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Optional opt) throws IOException { // write actual type if (!Optional.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_OPTIONAL); } // write content, using an array of size 0 or 1 var valueType = declaredType.getArgumentOrDefault(0); if (opt.isEmpty()) { writer.output.writeArrayHeader(0); } else { writer.output.writeArrayHeader(1); writer.writeObject(valueType, "", opt.get()); } } // writes an array, with meta type information if necessary private static void writeArray( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Object[] array) throws IOException { // write actual type var actualComponentType = array.getClass().getComponentType(); if (!declaredType.isArray() || declaredType.getRawType().getComponentType() != actualComponentType) { if (actualComponentType == String.class) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_STRING_ARRAY); } else if (actualComponentType == Object.class) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_OBJECT_ARRAY); } else { writeArrayTypeDescription(writer, array.getClass()); } } // write content var componentType = declaredType.toComponentType(); writer.output.writeArrayHeader(array.length); for (var item : array) { writer.writeObject(componentType, "", item); } } // writes a primitive array, with meta type information if necessary private static void writePrimitiveArray( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Object array) throws IOException { // write actual type var arrayType = array.getClass(); if (!declaredType.isArray()) { writeArrayTypeDescription(writer, arrayType); } // write content var arrayComponentType = arrayType.getComponentType(); var componentType = ResolvedType.of(arrayComponentType); var handler = JodaBeanPackedBinWriter.LOOKUP.get(arrayComponentType); var arrayLength = Array.getLength(array); writer.output.writeArrayHeader(arrayLength); for (int i = 0; i < arrayLength; i++) { handler.handle(writer, componentType, propertyName, Array.get(array, i)); } } // writes the meta type header private static final void writeArrayTypeDescription(JodaBeanPackedBinWriter writer, Class arrayType) throws IOException { var ref = writer.typeDefinitions.get(arrayType); if (ref == null) { var encodedClassName = metaTypeArrayName(arrayType.getComponentType()); writer.typeDefinitions.put(arrayType, writer.typeDefinitionIndex++); writer.output.writeTypeName(encodedClassName); } else { writer.output.writeTypeReference(ref); } } // determines the meta type name to use private static String metaTypeArrayName(Class valueType) { if (valueType.isArray()) { return metaTypeArrayName(valueType.getComponentType()) + "[]"; } if (valueType == Object.class) { return "Object[]"; } if (valueType == String.class) { return "String[]"; } return valueType.getName() + "[]"; } // writes an iterable, with meta type information if necessary private static void writeIterable( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Iterable iterable) throws IOException { // convert to a list, which is necessary as there is no size() on Iterable // this ensures that the generics of the iterable are retained var list = StreamSupport.stream(iterable::spliterator, Spliterator.ORDERED, false).toList(); var adjustedType = ResolvedType.of(List.class, declaredType.getArguments()); writeCollection(writer, adjustedType, propertyName, list); } // writes a collection, with meta type information if necessary private static void writeCollection( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Collection coll) throws IOException { // write actual type if (coll instanceof Set && !Set.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_SET); } else if (!Collection.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_LIST); } // write content var itemType = declaredType.getArgumentOrDefault(0); writer.output.writeArrayHeader(coll.size()); for (var item : coll) { writer.writeObject(itemType, "", item); } } // writes a map, with meta type information if necessary private static void writeMap( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Map map) throws IOException { // write actual type if (!Map.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_MAP); } // write content writeMapEntries(writer, declaredType, propertyName, map.entrySet()); } // writes a map given map entries, code shared with Multimap static void writeMapEntries( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Collection> mapEntries) throws IOException { var keyType = declaredType.getArgumentOrDefault(0); var valueType = declaredType.getArgumentOrDefault(1); writer.output.writeMapHeader(mapEntries.size()); for (var entry : mapEntries) { writer.writeObject(keyType, "", entry.getKey()); writer.writeObject(valueType, "", entry.getValue()); } } } //------------------------------------------------------------------------- private static sealed class GuavaBinHandlers extends BaseBinHandlers { @Override BinHandler createHandler(Class type) { if (com.google.common.base.Optional.class.isAssignableFrom(type)) { return (BinHandler>) GuavaBinHandlers::writeOptional; } if (Multimap.class.isAssignableFrom(type)) { return (BinHandler>) GuavaBinHandlers::writeMultimap; } if (Multiset.class.isAssignableFrom(type)) { return (BinHandler>) GuavaBinHandlers::writeMultiset; } if (Table.class.isAssignableFrom(type)) { return (BinHandler>) GuavaBinHandlers::writeTable; } if (BiMap.class.isAssignableFrom(type)) { return (BinHandler>) GuavaBinHandlers::writeBiMap; } return super.createHandler(type); } // writes an optional, with meta type information if necessary private static void writeOptional( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, com.google.common.base.Optional opt) throws IOException { // write actual type if (!com.google.common.base.Optional.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_OPTIONAL); } // write content, using an array of size 0 or 1 var valueType = declaredType.getArgumentOrDefault(0); if (opt.isPresent()) { writer.output.writeArrayHeader(1); writer.writeObject(valueType, "", opt.get()); } else { writer.output.writeArrayHeader(0); } } // writes a multimap, with meta type information if necessary private static void writeMultimap( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Multimap mmap) throws IOException { // write actual type if (mmap instanceof SetMultimap && !SetMultimap.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_SET_MULTIMAP); } else if (!Multimap.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_LIST_MULTIMAP); } // write content, using a map of key to array of values var keyType = declaredType.getArgumentOrDefault(0); var valueType = declaredType.getArgumentOrDefault(1); var map = mmap.asMap(); writer.output.writeMapHeader(map.size()); for (var entry : map.entrySet()) { writer.writeObject(keyType, "", entry.getKey()); var values = entry.getValue(); writer.output.writeArrayHeader(values.size()); for (var value : values) { writer.writeObject(valueType, "", value); } } } // writes a multiset, with meta type information if necessary private static void writeMultiset( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Multiset mset) throws IOException { // write actual type if (!Multiset.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_MULTISET); } // write content, using a map of value to count var valueType = declaredType.getArgumentOrDefault(0); var entrySet = mset.entrySet(); writer.output.writeMapHeader(entrySet.size()); for (var entry : entrySet) { writer.writeObject(valueType, "", entry.getElement()); writer.output.writeInt(entry.getCount()); } } // writes a table, with meta type information if necessary private static void writeTable( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Table table) throws IOException { // write actual type if (!Table.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_TABLE); } // write content, using a map of row to map of column to value var rowType = declaredType.getArgumentOrDefault(0); var columnType = declaredType.getArgumentOrDefault(1); var valueType = declaredType.getArgumentOrDefault(2); var rowMap = table.rowMap(); writer.output.writeMapHeader(rowMap.size()); for (var rowEntry : rowMap.entrySet()) { writer.writeObject(rowType, "", rowEntry.getKey()); writer.output.writeMapHeader(rowEntry.getValue().size()); for (var colEntry : rowEntry.getValue().entrySet()) { writer.writeObject(columnType, "", colEntry.getKey()); writer.writeObject(valueType, "", colEntry.getValue()); } } } // writes a BiMap, with meta type information if necessary private static void writeBiMap( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, BiMap biMap) throws IOException { // write actual type if (!BiMap.class.isAssignableFrom(declaredType.getRawType())) { // hack around Guava annoyance by assuming that size 0 and 1 ImmutableBiMap // was actually meant to be an ImmutableMap if ((declaredType.getRawType() != Map.class && declaredType.getRawType() != ImmutableMap.class) || biMap.size() >= 2) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_BIMAP); } else if (!Map.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_MAP); } } // write content writeMapEntries(writer, declaredType, propertyName, biMap.entrySet()); } } //------------------------------------------------------------------------- private static final class CollectBinHandlers extends GuavaBinHandlers { @Override BinHandler createHandler(Class type) { if (Grid.class.isAssignableFrom(type)) { return (BinHandler>) CollectBinHandlers::writeGrid; } return super.createHandler(type); } // writes a grid, with meta type information if necessary private static void writeGrid( JodaBeanPackedBinWriter writer, ResolvedType declaredType, String propertyName, Grid grid) throws IOException { // write actual type if (!Grid.class.isAssignableFrom(declaredType.getRawType())) { writer.output.writeTypeReference(BeanPack.TYPE_CODE_GRID); } // write content using sparse or dense approach var valueType = declaredType.getArgumentOrDefault(0); var rowCount = grid.rowCount(); var colCount = grid.columnCount(); var totalSize = rowCount * colCount; var gridSize = grid.size(); var sparse = gridSize <= (totalSize / 3d); writer.output.writeArrayHeader(3); writer.output.writeInt(sparse ? rowCount : -rowCount); writer.output.writeInt(colCount); if (sparse) { // sparse writer.output.writeArrayHeader(gridSize * 3); for (var cell : grid.cells()) { writer.output.writeInt(cell.getRow()); writer.output.writeInt(cell.getColumn()); writer.writeObject(valueType, "", cell.getValue()); } } else { // dense writer.output.writeArrayHeader(totalSize); for (var row = 0; row < rowCount; row++) { for (var column = 0; column < colCount; column++) { writer.writeObject(valueType, "", grid.get(row, column)); } } } } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanReferencingBinReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataInputStream; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerIterable; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; /** * Provides the ability for a Joda-Bean to read from the referencing binary format. */ class JodaBeanReferencingBinReader extends AbstractBinReader { /** * The base package including the trailing dot. */ private String overrideBasePackage; /** * The classes that have been serialized. */ private ClassInfo[] classes; /** * The classes for lookup of classInfo when the class is known and unnecessary to serialise. */ private Map, ClassInfo> classMap; /** * The serialized objects that are repeated and referenced. */ private Object[] refs; //----------------------------------------------------------------------- // creates an instance JodaBeanReferencingBinReader(JodaBeanSer settings, DataInputStream input) { super(settings, input); } //----------------------------------------------------------------------- // reads the input stream @Override T read(Class rootType) { try { try { return parseRemaining(rootType); } finally { input.close(); } } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } //----------------------------------------------------------------------- // parses the root bean @Override T parseRemaining(Class declaredType) throws Exception { // the array and version has already been read overrideBasePackage = declaredType.getPackage().getName() + "."; // ref count + class map parseClassDescriptions(); // parse var parsed = parseObject(declaredType, null, null, null, true); return declaredType.cast(parsed); } //----------------------------------------------------------------------- // parses the references private void parseClassDescriptions() throws Exception { var refCount = acceptInteger(input.readByte()); if (refCount < 0) { throw new IllegalArgumentException("Invalid binary data: Expected count of references, but was: " + refCount); } refs = new Object[refCount]; var classMapSize = acceptMap(input.readByte()); classes = new ClassInfo[classMapSize]; // Guaranteed non-negative by acceptMap() classMap = new HashMap<>(classMapSize); for (var position = 0; position < classMapSize; position++) { var classInfo = parseClassInfo(); classes[position] = classInfo; classMap.put(classInfo.type, classInfo); } } // parses the class information private ClassInfo parseClassInfo() throws Exception { var className = acceptString(input.readByte()); var type = SerTypeMapper.decodeType(className, settings, overrideBasePackage, null); var propertyCount = acceptArray(input.readByte()); if (propertyCount < 0) { throw new IllegalArgumentException("Invalid binary data: Expected array with 0 to many elements, but was: " + propertyCount); } var metaProperties = new MetaProperty[propertyCount]; if (ImmutableBean.class.isAssignableFrom(type)) { var deser = settings.getDeserializers().findDeserializer(type); var metaBean = deser.findMetaBean(type); for (var i = 0; i < propertyCount; i++) { var propertyName = acceptString(input.readByte()); metaProperties[i] = deser.findMetaProperty(type, metaBean, propertyName); } } else if (propertyCount != 0) { throw new IllegalArgumentException("Invalid binary data: Found non immutable bean class that has meta properties defined: " + type.getName() + ", " + propertyCount + " properties"); } return new ClassInfo(type, metaProperties); } // parses the bean using the class information private Object parseBean(int propertyCount, ClassInfo classInfo) { var propName = ""; if (classInfo.metaProperties.length != propertyCount) { throw new IllegalArgumentException("Invalid binary data: Expected " + classInfo.metaProperties.length + " properties but was: " + propertyCount); } try { var deser = settings.getDeserializers().findDeserializer(classInfo.type); var metaBean = deser.findMetaBean(classInfo.type); var builder = deser.createBuilder(classInfo.type, metaBean); for (var metaProp : classInfo.metaProperties) { if (metaProp == null) { MsgPackInput.skipObject(input); } else { propName = metaProp.name(); var value = parseObject(SerOptional.extractType(metaProp, classInfo.type), metaProp, classInfo.type, null, false); var wrappedValue = SerOptional.wrapValue(metaProp, classInfo.type, value); if (wrappedValue != null) { // null is the same as a value not being set // in the case of defaults we want those to take precedence deser.setValue(builder, metaProp, wrappedValue); } } propName = ""; } return deser.build(classInfo.type, builder); } catch (Exception ex) { throw new RuntimeException("Error parsing bean: " + classInfo.type.getName() + "::" + propName + ", " + ex.getMessage(), ex); } } //----------------------------------------------------------------------- @Override Object parseObject( Class declaredType, MetaProperty metaProp, Class beanType, SerIterable parentIterable, boolean rootType) throws Exception { // establish type Class effectiveType = declaredType; ClassInfo classInfo = null; String metaType = null; Integer ref = null; int typeByte = input.readByte(); // Unwrap nested references and metadata while (isMap(typeByte)) { input.mark(18); var mapSize = acceptMap(typeByte); if (mapSize > 0) { int typeByteTemp = input.readByte(); if (isIntExtension(typeByteTemp)) { var nestedTypeByteTemp = typeByteTemp; typeByteTemp = input.readByte(); var reference = acceptIntExtension(nestedTypeByteTemp); if (typeByteTemp == JODA_TYPE_DATA) { if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } classInfo = classes[reference]; if (!declaredType.isAssignableFrom(classInfo.type)) { throw new IllegalArgumentException("Specified type is incompatible with declared type: " + declaredType.getName() + " and " + classInfo.type.getName()); } typeByte = input.readByte(); } else if (typeByteTemp == JODA_TYPE_META) { if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } var value = refs[reference]; if (!(value instanceof String)) { throw new IllegalArgumentException("Invalid binary data: Expected reference to meta type name, but was: " + reference + ", " + value); } metaType = (String) value; typeByte = input.readByte(); } else if (typeByteTemp == JODA_TYPE_REF_KEY) { if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } // Regular object that is re-referenced // ref is the key, so the rest of the object needs to be placed in refs[ref] ref = reference; if (ref < 0 || ref > refs.length) { throw new IllegalArgumentException("Invalid binary data: Expected reference to position less than " + refs.length + ", but was: " + ref); } typeByte = input.readByte(); } else { input.reset(); break; } } else if (typeByteTemp == EXT_8) { var size = input.readUnsignedByte(); typeByteTemp = input.readByte(); if (typeByteTemp != JODA_TYPE_META) { throw new IllegalArgumentException("Invalid binary data: Expected meta information, but was: 0x" + toHex(typeByteTemp)); } if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } metaType = acceptStringBytes(size); typeByte = input.readByte(); } else if (isMap(typeByteTemp)) { mapSize = acceptMap(typeByteTemp); typeByteTemp = input.readByte(); // Check for nested JODA_TYPE_META with a reference as the key if (isIntExtension(typeByteTemp)) { var nestedTypeByteTemp = typeByteTemp; typeByteTemp = input.readByte(); var reference = acceptIntExtension(nestedTypeByteTemp); if (typeByteTemp == JODA_TYPE_REF_KEY) { if (mapSize != 1) { throw new IllegalArgumentException("Invalid binary data: Expected map size 1, but was: " + mapSize); } typeByteTemp = input.readByte(); // Check for nested JODA_TYPE_META if (typeByteTemp == EXT_8) { var size = input.readUnsignedByte(); typeByteTemp = input.readByte(); // Meta is the only type serialized using EXT_8 if (typeByteTemp != JODA_TYPE_META) { throw new IllegalArgumentException("Invalid binary data: Expected previous metatype, but was: 0x" + toHex(typeByteTemp)); } metaType = acceptStringBytes(size); refs[reference] = metaType; typeByte = input.readByte(); } else { input.reset(); break; } } else { input.reset(); break; } } else { input.reset(); break; } } else { input.reset(); break; } } else { input.reset(); break; } } if (isArray(typeByte)) { input.mark(11); var arraySize = acceptArray(typeByte); if (arraySize > 0) { int typeByteTemp = input.readByte(); if (isIntExtension(typeByteTemp)) { var nestedTypeByteTemp = typeByteTemp; typeByteTemp = input.readByte(); var reference = acceptIntExtension(nestedTypeByteTemp); if (typeByteTemp == JODA_TYPE_BEAN) { classInfo = classes[reference]; var bean = parseBean(declaredType, rootType, classInfo, arraySize); if (ref != null) { refs[ref] = bean; } return bean; } else { input.reset(); } } else { input.reset(); } } else { input.reset(); } } if (isIntExtension(typeByte)) { input.mark(5); int typeByteTemp = input.readByte(); var reference = acceptIntExtension(typeByte); // JODA_TYPE_REF is the only thing serialized in isolation, others are serialized as map keys or the start of an array if (typeByteTemp != JODA_TYPE_REF) { throw new IllegalArgumentException("Invalid binary data: Expected reference to previous object, but was: 0x" + toHex(typeByteTemp)); } var value = refs[reference]; if (value == null) { throw new IllegalArgumentException("Invalid binary data: Expected reference to previous object, but was null: " + reference); } return value; } if (classInfo != null) { effectiveType = classInfo.type; } var value = parseObject(metaProp, beanType, parentIterable, effectiveType, metaType, typeByte); if (ref != null) { refs[ref] = value; // This object was keyed and is repeated } return value; } private Object parseObject( MetaProperty metaProp, Class beanType, SerIterable parentIterable, Class effectiveType, String metaType, int typeByte) throws Exception { // parse based on type if (typeByte == NIL) { return null; } if (Bean.class.isAssignableFrom(effectiveType)) { if (isArray(typeByte)) { var arraySize = acceptArray(typeByte); var classInfo = classMap.computeIfAbsent(effectiveType, this::lookupClassInfo); return parseBean(arraySize, classInfo); } else { return parseSimple(typeByte, effectiveType); } } else { if (isMap(typeByte) || isArray(typeByte)) { SerIterable childIterable = null; if (metaType != null) { childIterable = settings.getIteratorFactory().createIterable(metaType, settings, null); } else if (metaProp != null) { childIterable = settings.getIteratorFactory().createIterable(metaProp, beanType); } else if (parentIterable != null) { childIterable = settings.getIteratorFactory().createIterable(parentIterable); } if (childIterable == null) { throw new IllegalArgumentException("Invalid binary data: Invalid metaType: " + metaType); } return parseIterable(typeByte, childIterable); } else { return parseSimple(typeByte, effectiveType); } } } // looks up information of classes that are not known upfront, e.g. are used by custom de-serializers private ClassInfo lookupClassInfo(Class type) { var deser = settings.getDeserializers().findDeserializer(type); var metaBean = deser.findMetaBean(type); if (metaBean == null) { throw new RuntimeException("Could not find type: " + type.getName()); } var propertyCount = metaBean.metaPropertyCount(); var metaProperties = new MetaProperty[propertyCount]; var i = 0; for (var metaProperty : metaBean.metaPropertyIterable()) { metaProperties[i++] = metaProperty; } return new ClassInfo(type, metaProperties); } private Object parseBean(Class declaredType, boolean rootType, ClassInfo classInfo, int arraySize) { if (rootType) { if (!Bean.class.isAssignableFrom(classInfo.type)) { throw new IllegalArgumentException("Root type is not a Joda-Bean: " + classInfo.type.getName()); } overrideBasePackage = classInfo.type.getPackage().getName() + "."; } if (!declaredType.isAssignableFrom(classInfo.type)) { throw new IllegalArgumentException("Specified type is incompatible with declared type: " + declaredType.getName() + " and " + classInfo.type.getName()); } return parseBean(arraySize - 1, classInfo); } //----------------------------------------------------------------------- private boolean isIntExtension(int typeByte) { return typeByte == MsgPack.FIX_EXT_1 || typeByte == MsgPack.FIX_EXT_2 || typeByte == MsgPack.FIX_EXT_4; } private int acceptIntExtension(int typeByte) throws IOException { return switch (typeByte) { case MsgPack.FIX_EXT_1 -> input.readUnsignedByte(); case MsgPack.FIX_EXT_2 -> input.readUnsignedShort(); case MsgPack.FIX_EXT_4 -> input.readInt(); default -> throw new IllegalArgumentException( "Invalid binary data: Expected int extension type, but was: 0x" + toHex(typeByte)); }; } //----------------------------------------------------------------------- // The info needed to deserialize instances of a class with a reference to the initially serialized class definition private static final class ClassInfo { // The class itself private final Class type; // The metaproperties (empty if not a bean) in the order in which they need to be serialized private final MetaProperty[] metaProperties; private ClassInfo(Class type, MetaProperty[] metaProperties) { this.type = type; this.metaProperties = metaProperties; } @Override public String toString() { return "ClassInfo{" + "type=" + type + ", metaProperties=" + Arrays.toString(metaProperties) + '}'; } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanReferencingBinWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.IOException; import java.io.OutputStream; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; /** * Provides the ability for a Joda-Bean to written to the referencing binary format. */ class JodaBeanReferencingBinWriter extends AbstractBinWriter { private BeanReferences references; // creates an instance JodaBeanReferencingBinWriter(JodaBeanSer settings, OutputStream output) { super(settings, output); } //----------------------------------------------------------------------- // writes the bean void write(Bean bean) throws IOException { if (!(bean instanceof ImmutableBean immutable)) { throw new IllegalArgumentException( "Referencing binary format can only write ImmutableBean instances: " + bean.getClass().getName()); } // sets up the map of beans - classes & classSerializationCount references = BeanReferences.find(immutable, settings); // write array of 4 items - Version, Ref Count, Class Info, Root Bean output.writeArrayHeader(4); output.writeInt(2); writeClassDescriptions(references); writeRootBean(bean, true); } // determines what beans occur more than once and setup references private void writeClassDescriptions(BeanReferences references) throws IOException { // write out ref count first, which is the number of instances that are referenced output.writeInt(references.getReferences().size()); // write map of class name to a list of metatype names (which is empty if not a bean) var classInfos = references.getClassInfoList(); output.writeMapHeader(classInfos.size()); for (var classInfo : classInfos) { // known types parameter is null as we never serialize the class names again var className = SerTypeMapper.encodeType(classInfo.type, settings, null, null); output.writeString(className); output.writeArrayHeader(classInfo.metaProperties.size()); for (MetaProperty property : classInfo.metaProperties) { output.writeString(property.name()); } } } //----------------------------------------------------------------------- @Override void writeBean(Bean bean, Class declaredType, RootType rootTypeFlag) throws IOException { var ref = references.getReferences().get(bean); if (ref != null) { if (ref.hasBeenSerialized) { output.writePositiveExtensionInt(MsgPack.JODA_TYPE_REF, ref.position); return; } output.writeMapHeader(1); output.writePositiveExtensionInt(MsgPack.JODA_TYPE_REF_KEY, ref.position); } var classInfo = references.getClassInfo(bean.getClass()); var props = classInfo.metaProperties; var count = props.size(); var values = new Object[count]; var size = 0; for (var prop : props) { var value = SerOptional.extractValue(prop, bean); values[size++] = value; } if (rootTypeFlag == RootType.ROOT_WITH_TYPE || (rootTypeFlag == RootType.NOT_ROOT && bean.getClass() != declaredType)) { output.writeArrayHeader(size + 1); output.writePositiveExtensionInt(MsgPack.JODA_TYPE_BEAN, classInfo.position); } else { output.writeArrayHeader(size); } for (var i = 0; i < size; i++) { var prop = props.get(i); var value = values[i]; var propType = SerOptional.extractType(prop, bean.getClass()); if (value == null) { output.writeNil(); continue; } if (value instanceof Bean beanValue) { if (settings.getConverter().isConvertible(value.getClass())) { writeSimple(propType, value); } else { writeBean(beanValue, propType, RootType.NOT_ROOT); } } else { var itemIterator = settings.getIteratorFactory().create(value, prop, bean.getClass()); if (itemIterator != null) { writeElements(itemIterator); } else { writeSimple(propType, value); } } } if (ref != null) { ref.sent(); } } @Override void writeMetaPropertyReference(String metaTypeName) throws IOException { var ref = references.getReferences().get(metaTypeName); if (ref != null) { if (ref.hasBeenSerialized) { output.writePositiveExtensionInt(MsgPack.JODA_TYPE_META, ref.position); } else { output.writeMapHeader(1); output.writePositiveExtensionInt(MsgPack.JODA_TYPE_REF_KEY, ref.position); output.writeExtensionString(MsgPack.JODA_TYPE_META, metaTypeName); ref.sent(); } } else { output.writeExtensionString(MsgPack.JODA_TYPE_META, metaTypeName); } } @Override Class getAndSerializeEffectiveTypeIfRequired(Object value, Class declaredType) throws IOException { var ref = references.getReferences().get(value); if (ref != null && ref.hasBeenSerialized) { // Don't need to change types if using a reference return declaredType; } var realType = value.getClass(); var effectiveType = declaredType; if (declaredType == Object.class) { if (realType != String.class) { effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); var classInfo = references.getClassInfo(effectiveType); output.writeMapHeader(1); output.writePositiveExtensionInt(MsgPack.JODA_TYPE_DATA, classInfo.position); } else { effectiveType = realType; } } else if (!settings.getConverter().isConvertible(declaredType)) { effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); var classInfo = references.getClassInfo(effectiveType); output.writeMapHeader(1); output.writePositiveExtensionInt(MsgPack.JODA_TYPE_DATA, classInfo.position); } return effectiveType; } @Override void writeObjectAsString(Object value, Class effectiveType) throws IOException { var ref = references.getReferences().get(value); if (ref != null && ref.hasBeenSerialized) { output.writePositiveExtensionInt(MsgPack.JODA_TYPE_REF, ref.position); } else { var converted = settings.getConverter().convertToString(effectiveType, value); if (converted == null) { throw new IllegalArgumentException("Unable to write because converter returned a null string: " + value); } if (ref != null) { output.writeMapHeader(1); output.writePositiveExtensionInt(MsgPack.JODA_TYPE_REF_KEY, ref.position); output.writeString(converted); ref.sent(); } else { output.writeString(converted); } } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanStandardBinReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataInputStream; import org.joda.beans.ser.JodaBeanSer; /** * Provides the ability for a Joda-Bean to read from the standard binary format. */ class JodaBeanStandardBinReader extends AbstractBinReader { // creates an instance JodaBeanStandardBinReader(JodaBeanSer settings, DataInputStream input) { super(settings, input); } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/JodaBeanStandardBinWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.Spliterator; import java.util.stream.StreamSupport; import org.joda.beans.Bean; import org.joda.beans.ResolvedType; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTypeMapper; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableGrid; import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.SetMultimap; import com.google.common.collect.Table; /** * Writes a Joda-Bean in standard binary format. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ final class JodaBeanStandardBinWriter { // why is there an ugly ClassValue setup here? // because this is O(1) whereas switch with pattern match which is O(n) private static final ClassValue> LOOKUP = new ClassValue<>() { @SuppressWarnings("rawtypes") // sneaky use of raw type to allow typed value in each method below @Override protected BinHandler computeValue(Class type) { if (Bean.class.isAssignableFrom(type)) { return (BinHandler) JodaBeanStandardBinWriter::writeBeanMaybeSimple; } // these primitive types are always written and interpretted without a type if (type == String.class) { return (writer, declaredType, propName, value) -> writer.output.writeString((String) value); } if (type == Integer.class || type == int.class) { return (writer, declaredType, propName, value) -> writer.output.writeInt((Integer) value); } if (type == Double.class || type == double.class) { return (writer, declaredType, propName, value) -> writer.output.writeDouble((Double) value); } if (type == Float.class || type == float.class) { return (writer, declaredType, propName, value) -> writer.output.writeFloat((Float) value); } if (type == Boolean.class || type == boolean.class) { return (writer, declaredType, propName, value) -> writer.output.writeBoolean((Boolean) value); } return BaseBinHandlers.INSTANCE.createHandler(type); } }; /** * The settings to use. */ private final JodaBeanSer settings; /** * The outputter. */ private final MsgPackOutput output; /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map, String> knownTypes = new HashMap<>(); /** * Creates an instance. * * @param settings the settings to use, not null * @param out the output stream, not null */ JodaBeanStandardBinWriter(JodaBeanSer settings, OutputStream out) { this.settings = settings; this.output = new MsgPackOutput(out); } //------------------------------------------------------------------------- /** * Writes the bean to the {@code OutputStream}. * * @param bean the bean to output, not null * @param includeRootType whether to include the root type * @throws IOException if an error occurs */ void write(Bean bean, boolean includeRootType) throws IOException { var rootType = includeRootType ? ResolvedType.OBJECT : ResolvedType.of(bean.getClass()); output.writeArrayHeader(2); output.writeInt(1); // version 1 // root always outputs the bean, not Joda-Convert form writeBean(rootType, "", bean, includeRootType); } //----------------------------------------------------------------------- // writes an object, by determining the runtime type private void writeObject(ResolvedType declaredType, String propertyName, Object value) throws IOException { if (value == null) { output.writeNil(); } else { var handler = LOOKUP.get(value.getClass()); handler.handle(this, declaredType, propertyName, value); } } //------------------------------------------------------------------------- // writes a bean, favouring output as a Joda-Convert type private void writeBeanMaybeSimple(ResolvedType declaredType, String propertyName, Bean bean) throws IOException { // check for Joda-Convert cannot be in ClassValue as it relies on the settings if (settings.getConverter().isConvertible(bean.getClass())) { writeSimple(declaredType, propertyName, bean); } else { writeBean(declaredType, propertyName, bean, false); } } // writes a bean, with meta type information if necessary private void writeBean(ResolvedType declaredType, String propertyName, Bean bean, boolean isRootAndInclRootType) throws IOException { // have to determine the number of properties being output before starting to write var count = bean.metaBean().metaPropertyCount(); var propHandlers = new PropertyHandler[count]; var size = 0; for (var metaProperty : bean.metaBean().metaPropertyIterable()) { if (settings.isSerialized(metaProperty)) { var value = metaProperty.get(bean); if (value != null) { var resolvedType = metaProperty.propertyResolvedType(bean.getClass()); var handler = LOOKUP.get(value.getClass()); // package up each write in a lambda, avoiding a second lookup var propHandler = handler.handleProperty(this, resolvedType, metaProperty.name(), value); if (propHandler != null) { propHandlers[size++] = propHandler; } } } } // write out the header, potentially including the type if (bean.getClass() != declaredType.getRawType()) { var typeStr = SerTypeMapper.encodeType(bean.getClass(), settings, basePackage, knownTypes); if (isRootAndInclRootType) { basePackage = bean.getClass().getPackage().getName() + "."; } output.writeMapHeader(size + 1); output.writeExtensionString(MsgPack.JODA_TYPE_BEAN, typeStr); output.writeNil(); } else { output.writeMapHeader(size); } // write each property for (int i = 0; i < size; i++) { propHandlers[i].handle(); } } //----------------------------------------------------------------------- // writes a simple type, with meta type information if necessary private void writeSimple(ResolvedType declaredType, String propertyName, Object value) throws IOException { // when int/double/float/boolean are parsed they are treated as being of that exact type // long/short/byte require type metadata // also handle no declared type and subclasses var effectiveType = getAndSerializeEffectiveTypeIfRequired(value, declaredType.getRawType()); // currently favouring == checks over pattern match switch var type = value.getClass(); if (type == Long.class) { output.writeLong((Long) value); } else if (type == Short.class) { output.writeInt((Short) value); } else if (type == Byte.class) { output.writeInt((Byte) value); } else if (type == byte[].class) { output.writeBytes((byte[]) value); } else { writeJodaConvert(effectiveType, propertyName, value); } } // called when serializing an object in {@link #writeSimple(Class, Object)}, to get the effective type of the // object and if necessary to serialize the class information // needs to handle no declared type and subclass instances private Class getAndSerializeEffectiveTypeIfRequired(Object value, Class declaredType) throws IOException { var realType = value.getClass(); if (declaredType == Object.class) { if (realType != String.class) { var effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); output.writeMapHeader(1); var type = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); output.writeExtensionString(MsgPack.JODA_TYPE_DATA, type); return effectiveType; } else { return realType; } } if (!settings.getConverter().isConvertible(declaredType)) { var effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); output.writeMapHeader(1); var type = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); output.writeExtensionString(MsgPack.JODA_TYPE_DATA, type); return effectiveType; } return declaredType; } // writes the object as a String using Joda-Convert private void writeJodaConvert(Class effectiveType, String propertyName, Object value) throws IOException { try { var converted = settings.getConverter().convertToString(effectiveType, value); if (converted == null) { throw invalidNullString(propertyName, value); } output.writeString(converted); } catch (RuntimeException ex) { throw invalidConversionMsg(propertyName, value, ex); } } private static IllegalArgumentException invalidNullString(String propertyName, Object value) throws IOException { return new IllegalArgumentException( "Unable to write property '" + propertyName + "' because converter returned a null string: " + value); } private IllegalArgumentException invalidConversionMsg(String propertyName, Object value, RuntimeException ex) { var msg = "Unable to write property '" + propertyName + "', type " + value.getClass().getName() + " could not be converted to a String"; return new IllegalArgumentException(msg, ex); } // writes the meta type header private static final void writeMetaType(JodaBeanStandardBinWriter writer, String metaTypeName) throws IOException { writer.output.writeMapHeader(1); writer.output.writeExtensionString(MsgPack.JODA_TYPE_META, metaTypeName); } // gets the weakened type, which exists for backwards compatibility // once the parser can handle ResolvedType this method can, in theory, be removed private static ResolvedType toWeakenedType(ResolvedType base) { for (var arg : base.getArguments()) { var rawType = arg.getRawType(); if (LOOKUP.get(rawType).isCollection(rawType)) { return base.toRaw(); } } return base; } //------------------------------------------------------------------------- private static interface BinHandler { public abstract void handle( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, T obj) throws IOException; public default PropertyHandler handleProperty( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, T obj) { return () -> { writer.output.writeString(propertyName); handle(writer, declaredType, propertyName, obj); }; } public default boolean isCollection(Class type) { return false; } } private static interface CollectionBinHandler extends BinHandler { @Override public default boolean isCollection(Class type) { return true; } } //------------------------------------------------------------------------- // like Runnable, but with IOException private static interface PropertyHandler { public abstract void handle() throws IOException; } //------------------------------------------------------------------------- // handles base JDK collections private static sealed class BaseBinHandlers { // an instance loaded dependent on the classpath private static final BaseBinHandlers INSTANCE = getInstance(); private static final BaseBinHandlers getInstance() { try { ImmutableGrid.of(); // check if class is available return new CollectBinHandlers(); } catch (Exception | LinkageError ex) { try { ImmutableMultiset.of(); // check if class is available return new GuavaBinHandlers(); } catch (Exception | LinkageError ex2) { return new BaseBinHandlers(); } } } // creates the handler, called from ClassValue.computeValue() BinHandler createHandler(Class type) { if (type == Optional.class) { return OptionalBinHandler.INSTANCE; } if (type.isArray()) { var componentType = type.getComponentType(); if (componentType.isPrimitive()) { if (componentType == byte.class) { return JodaBeanStandardBinWriter::writeSimple; } else { return (CollectionBinHandler) BaseBinHandlers::writePrimitiveArray; } } else { return (CollectionBinHandler) BaseBinHandlers::writeArray; } } if (Map.class.isAssignableFrom(type)) { return (CollectionBinHandler>) BaseBinHandlers::writeMap; } if (Collection.class.isAssignableFrom(type)) { return (CollectionBinHandler>) BaseBinHandlers::writeCollection; } if (Iterable.class.isAssignableFrom(type)) { return (CollectionBinHandler>) BaseBinHandlers::writeIterable; } return JodaBeanStandardBinWriter::writeSimple; } // writes an array, with meta type information if necessary private static void writeArray( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Object[] array) throws IOException { // write actual type var valueType = array.getClass().getComponentType(); if (valueType == Object.class && !Object[].class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, metaTypeArrayName(valueType)); } else if (valueType == String.class && !String[].class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, metaTypeArrayName(valueType)); } // write content var componentType = toWeakenedType(declaredType.toComponentType()); writer.output.writeArrayHeader(array.length); for (var item : array) { writer.writeObject(componentType, "", item); } } // writes a primitive array, with meta type information if necessary private static void writePrimitiveArray( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Object array) throws IOException { // write actual type var valueType = array.getClass().getComponentType(); if (!declaredType.isArray()) { writeMetaType(writer, metaTypeArrayName(valueType)); } // write content var componentType = declaredType.toComponentType(); var handler = JodaBeanStandardBinWriter.LOOKUP.get(componentType.getRawType()); var arrayLength = Array.getLength(array); writer.output.writeArrayHeader(arrayLength); for (int i = 0; i < arrayLength; i++) { handler.handle(writer, componentType, propertyName, Array.get(array, i)); } } // determines the meta type name to use private static String metaTypeArrayName(Class valueType) { if (valueType.isArray()) { return metaTypeArrayName(valueType.getComponentType()) + "[]"; } if (valueType == Object.class) { return "Object[]"; } if (valueType == String.class) { return "String[]"; } return valueType.getName() + "[]"; } // writes an iterable, with meta type information if necessary private static void writeIterable( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Iterable iterable) throws IOException { // convert to a list, which is necessary as there is no size() on Iterable // this ensures that the generics of the iterable are retained var list = StreamSupport.stream(iterable::spliterator, Spliterator.ORDERED, false).toList(); var adjustedType = ResolvedType.of(List.class, declaredType.getArguments()); writeCollection(writer, adjustedType, propertyName, list); } // writes a collection, with meta type information if necessary private static void writeCollection( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Collection coll) throws IOException { // write actual type if (coll instanceof Set && !Set.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Set"); } else if (coll instanceof List && !List.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "List"); } else if (!Collection.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Collection"); } // write content var itemType = toWeakenedType(declaredType.getArgumentOrDefault(0)); writer.output.writeArrayHeader(coll.size()); for (var item : coll) { writer.writeObject(itemType, "", item); } } // writes a map, with meta type information if necessary private static void writeMap( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Map map) throws IOException { // write actual type if (!Map.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Map"); } // write content writeMapEntries(writer, declaredType, propertyName, map.entrySet()); } // writes a map given map entries, code shared with Multimap static void writeMapEntries( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Collection> mapEntries) throws IOException { var keyType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var valueType = toWeakenedType(declaredType.getArgumentOrDefault(1)); writer.output.writeMapHeader(mapEntries.size()); for (var entry : mapEntries) { writer.writeObject(keyType, "", entry.getKey()); writer.writeObject(valueType, "", entry.getValue()); } } } //------------------------------------------------------------------------- private static sealed class GuavaBinHandlers extends BaseBinHandlers { @Override BinHandler createHandler(Class type) { if (Multimap.class.isAssignableFrom(type)) { return (CollectionBinHandler>) GuavaBinHandlers::writeMultimap; } if (Multiset.class.isAssignableFrom(type)) { return (CollectionBinHandler>) GuavaBinHandlers::writeMultiset; } if (Table.class.isAssignableFrom(type)) { return (CollectionBinHandler>) GuavaBinHandlers::writeTable; } if (BiMap.class.isAssignableFrom(type)) { return (CollectionBinHandler>) GuavaBinHandlers::writeBiMap; } if (com.google.common.base.Optional.class.isAssignableFrom(type)) { return GuavaOptionalBinHandler.INSTANCE; } return super.createHandler(type); } // writes a multimap, with meta type information if necessary private static void writeMultimap( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Multimap mmap) throws IOException { // write actual type if (mmap instanceof SetMultimap && !SetMultimap.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "SetMultimap"); } else if (mmap instanceof ListMultimap && !ListMultimap.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "ListMultimap"); } else if (!Multimap.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Multimap"); } // write content, using a map with repeated keys writeMapEntries(writer, declaredType, propertyName, mmap.entries()); } // writes a multiset, with meta type information if necessary private static void writeMultiset( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Multiset mset) throws IOException { // write actual type if (!Multiset.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Multiset"); } // write content, using a map of value to count var valueType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var entrySet = mset.entrySet(); writer.output.writeMapHeader(entrySet.size()); for (var entry : entrySet) { writer.writeObject(valueType, "", entry.getElement()); writer.output.writeInt(entry.getCount()); } } // writes a table, with meta type information if necessary private static void writeTable( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Table table) throws IOException { // write actual type if (!Table.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Table"); } // write content, using an array of cells var rowType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var columnType = toWeakenedType(declaredType.getArgumentOrDefault(1)); var valueType = toWeakenedType(declaredType.getArgumentOrDefault(2)); writer.output.writeArrayHeader(table.size()); for (var cell : table.cellSet()) { writer.output.writeArrayHeader(3); writer.writeObject(rowType, "", cell.getRowKey()); writer.writeObject(columnType, "", cell.getColumnKey()); writer.writeObject(valueType, "", cell.getValue()); } } // writes a BiMap, with meta type information if necessary private static void writeBiMap( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, BiMap biMap) throws IOException { // write actual type if (!BiMap.class.isAssignableFrom(declaredType.getRawType())) { // hack around Guava annoyance by assuming that size 0 and 1 ImmutableBiMap // was actually meant to be an ImmutableMap if ((declaredType.getRawType() != Map.class && declaredType.getRawType() != ImmutableMap.class) || biMap.size() >= 2) { writeMetaType(writer, "BiMap"); } else if (!Map.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Map"); } } // write content writeMapEntries(writer, declaredType, propertyName, biMap.entrySet()); } } //------------------------------------------------------------------------- private static final class CollectBinHandlers extends GuavaBinHandlers { @Override BinHandler createHandler(Class type) { if (Grid.class.isAssignableFrom(type)) { return (CollectionBinHandler>) CollectBinHandlers::writeGrid; } return super.createHandler(type); } // writes a grid, with meta type information if necessary private static void writeGrid( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Grid grid) throws IOException { // write actual type if (!Grid.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Grid"); } // write content using sparse or dense approach var valueType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var rows = grid.rowCount(); var columns = grid.columnCount(); var totalSize = rows * columns; var gridSize = grid.size(); if (gridSize < (totalSize / 4)) { // sparse writer.output.writeArrayHeader(gridSize + 2); writer.output.writeInt(rows); writer.output.writeInt(columns); for (var cell : grid.cells()) { writer.output.writeArrayHeader(3); writer.output.writeInt(cell.getRow()); writer.output.writeInt(cell.getColumn()); writer.writeObject(valueType, "", cell.getValue()); } } else { // dense writer.output.writeArrayHeader(totalSize + 2); writer.output.writeInt(rows); writer.output.writeInt(columns); for (var row = 0; row < rows; row++) { for (var column = 0; column < columns; column++) { writer.writeObject(valueType, "", grid.get(row, column)); } } } } } //------------------------------------------------------------------------- static final class OptionalBinHandler implements BinHandler> { private static final OptionalBinHandler INSTANCE = new OptionalBinHandler(); // when Optional is not a property, it is processed as a kind of collection @Override public void handle( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Optional opt) throws IOException { if (!Optional.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "Optional"); } var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.writeObject(valueType, "", opt.orElse(null)); } // when Optional is a property, it is ignored if empty @Override public PropertyHandler handleProperty( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, Optional opt) { return opt .map(value -> (PropertyHandler) () -> { var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.output.writeString(propertyName); writer.writeObject(valueType, propertyName, value); }) .orElse(null); } } //------------------------------------------------------------------------- static final class GuavaOptionalBinHandler implements BinHandler> { private static final GuavaOptionalBinHandler INSTANCE = new GuavaOptionalBinHandler(); // when Optional is not a property, it is processed as a kind of collection @Override public void handle( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, com.google.common.base.Optional opt) throws IOException { if (!com.google.common.base.Optional.class.isAssignableFrom(declaredType.getRawType())) { writeMetaType(writer, "GuavaOptional"); } // write content var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.writeObject(valueType, "", opt.orNull()); } // when Optional is a property, it is ignored if empty @Override public PropertyHandler handleProperty( JodaBeanStandardBinWriter writer, ResolvedType declaredType, String propertyName, com.google.common.base.Optional opt) { return opt .transform(value -> (PropertyHandler) () -> { var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.output.writeString(propertyName); writer.writeObject(valueType, propertyName, value); }) .orNull(); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/MsgPack.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; /** * Constants used in MsgPack binary serialization. *

* This uses the v2.0 specification of MsgPack as of 2014-01-29. */ abstract class MsgPack { /** * UTF-8 encoding. */ static final Charset UTF_8 = StandardCharsets.UTF_8; /** * Maximum fixed int. */ static final int MAX_FIX_INT = 0x7F; /** * Minimum fixed int. */ static final int MIN_FIX_INT = 0xFFFFFFE0; /** * Min fixed map - up to length 15. */ static final int MIN_FIX_MAP = 0xFFFFFF80; /** * Max fixed map. */ static final int MAX_FIX_MAP = 0xFFFFFF8F; /** * Min fixed array - up to length 15. */ static final int MIN_FIX_ARRAY = 0xFFFFFF90; /** * Max fixed array. */ static final int MAX_FIX_ARRAY = 0xFFFFFF9F; /** * Min fixed string - up to length 31. */ static final int MIN_FIX_STR = 0xFFFFFFA0; /** * Max fixed string. */ static final int MAX_FIX_STR = 0xFFFFFFBF; /** * Nil. */ static final int NIL = 0xFFFFFFC0; /** * False. */ static final int FALSE = 0xFFFFFFC2; /** * True. */ static final int TRUE = 0xFFFFFFC3; /** * Binary - up to length 255. */ static final int BIN_8 = 0xFFFFFFC4; /** * Binary - up to length (2^16)-1. */ static final int BIN_16 = 0xFFFFFFC5; /** * Binary - up to length (2^32)-1. */ static final int BIN_32 = 0xFFFFFFC6; /** * Extension - up to length 255. */ static final int EXT_8 = 0xFFFFFFC7; /** * Extension - up to length (2^16)-1. */ static final int EXT_16 = 0xFFFFFFC8; /** * Extension - up to length (2^32)-1. */ static final int EXT_32 = 0xFFFFFFC9; /** * Float - 4 bytes. */ static final int FLOAT_32 = 0xFFFFFFCA; /** * Double - 8 bytes. */ static final int FLOAT_64 = 0xFFFFFFCB; /** * Int (unsigned) - up to 1 byte. */ static final int UINT_8 = 0xFFFFFFCC; /** * Int (unsigned) - up to 2 bytes. */ static final int UINT_16 = 0xFFFFFFCD; /** * Int (unsigned) - up to 4 bytes. */ static final int UINT_32 = 0xFFFFFFCE; /** * Int (unsigned) - up to 8 bytes. */ static final int UINT_64 = 0xFFFFFFCF; /** * Int (signed) - up to 1 byte. */ static final int SINT_8 = 0xFFFFFFD0; /** * Int (signed) - up to 2 bytes. */ static final int SINT_16 = 0xFFFFFFD1; /** * Int (signed) - up to 4 bytes. */ static final int SINT_32 = 0xFFFFFFD2; /** * Int (signed) - up to 8 bytes. */ static final int SINT_64 = 0xFFFFFFD3; /** * Fixed extension - 1 byte. */ static final int FIX_EXT_1 = 0xFFFFFFD4; /** * Fixed extension - 2 bytes. */ static final int FIX_EXT_2 = 0xFFFFFFD5; /** * Fixed extension - 4 bytes. */ static final int FIX_EXT_4 = 0xFFFFFFD6; /** * Fixed extension - 8 bytes. */ static final int FIX_EXT_8 = 0xFFFFFFD7; /** * Fixed extension - 16 bytes. */ static final int FIX_EXT_16 = 0xFFFFFFD8; /** * String - up to length 255. */ static final int STR_8 = 0xFFFFFFD9; /** * String - up to length (2^16)-1. */ static final int STR_16 = 0xFFFFFFDA; /** * String - up to length (2^32)-1. */ static final int STR_32 = 0xFFFFFFDB; /** * Array - up to length (2^16)-1. */ static final int ARRAY_16 = 0xFFFFFFDC; /** * Array - up to length (2^32)-1. */ static final int ARRAY_32 = 0xFFFFFFDD; /** * Map - up to length (2^16)-1. */ static final int MAP_16 = 0xFFFFFFDE; /** * Map - up to length (2^32)-1. */ static final int MAP_32 = 0xFFFFFFDF; /** * Extension type code for a Joda-Bean bean-type. */ static final int JODA_TYPE_BEAN = 32; /** * Extension type code for a Joda-Bean simple-type. */ static final int JODA_TYPE_DATA = 33; /** * Extension type code for a Joda-Bean meta-type. */ static final int JODA_TYPE_META = 34; /** * Extension type code for a Joda-Bean serialized reference. */ static final int JODA_TYPE_REF_KEY = 35; /** * Extension type code for a reference to a previously serialized Joda-Bean. */ static final int JODA_TYPE_REF = 36; //----------------------------------------------------------------------- /** * Converts a byte to a hex string for debugging. * * @param b the byte * @return the two character hex equivalent, not null */ static String toHex(int b) { return String.format("%02X", (byte) b); } static boolean isMap(int typeByte) { return (typeByte >= MIN_FIX_MAP && typeByte <= MAX_FIX_MAP) || typeByte == MAP_16 || typeByte == MAP_32; } static boolean isArray(int typeByte) { return (typeByte >= MIN_FIX_ARRAY && typeByte <= MAX_FIX_ARRAY) || typeByte == ARRAY_16 || typeByte == ARRAY_32; } static boolean isString(int typeByte) { return (typeByte >= MIN_FIX_STR && typeByte <= MAX_FIX_STR) || typeByte == STR_8 || typeByte == STR_16 || typeByte == STR_32; } static boolean isIntegral(int typeByte) { return (typeByte >= MIN_FIX_INT && typeByte <= MAX_FIX_INT) || typeByte == UINT_8 || typeByte == UINT_16 || typeByte == UINT_32 || typeByte == UINT_64 || typeByte == SINT_8 || typeByte == SINT_16 || typeByte == SINT_32 || typeByte == SINT_64; } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/MsgPackInput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; /** * Receives and processes MsgPack data. */ abstract class MsgPackInput extends MsgPack { /** * The stream to read. */ private final DataInputStream input; /** * Creates an instance. * * @param bytes the bytes to read, not null */ MsgPackInput(byte[] bytes) { this(new ByteArrayInputStream(bytes)); } /** * Creates an instance. * * @param stream the stream to read from, not null */ MsgPackInput(InputStream stream) { this(new DataInputStream(stream)); } /** * Creates an instance. * * @param stream the stream to read from, not null */ MsgPackInput(DataInputStream stream) { this.input = stream; } //----------------------------------------------------------------------- /** * Reads all the data in the stream, closing the stream. */ void readAll() { try { try { var b = input.read(); while (b >= 0) { readObject(b); b = input.read(); } } finally { input.close(); } } catch (IOException ex) { throw new IllegalStateException(ex); } } //----------------------------------------------------------------------- void readObject(int unsigned) throws IOException { handleObjectStart(); var b = (byte) unsigned; if (b >= MIN_FIX_INT) { // no need to check for b <= MAX_FIX_INT handleInt(b); } else if (b >= MIN_FIX_STR && b <= MAX_FIX_STR) { string(b - MIN_FIX_STR); } else if (b >= MIN_FIX_ARRAY && b <= MAX_FIX_ARRAY) { array(b - MIN_FIX_ARRAY); } else if (b >= MIN_FIX_MAP && b <= MAX_FIX_MAP) { map(b - MIN_FIX_MAP); } else { switch (b) { case NIL -> handleNil(); case FALSE -> handleBoolean(false); case TRUE -> handleBoolean(true); case BIN_8 -> binary(input.readUnsignedByte()); case BIN_16 -> binary(input.readUnsignedShort()); case BIN_32 -> binary(input.readInt()); case EXT_8 -> extension(input.readUnsignedByte(), false); case EXT_16 -> extension(input.readUnsignedShort(), false); case EXT_32 -> extension(input.readInt(), false); case FLOAT_32 -> handleFloat(input.readFloat()); case FLOAT_64 -> handleDouble(input.readDouble()); case UINT_8 -> handleInt(input.readUnsignedByte()); case UINT_16 -> handleInt(input.readUnsignedShort()); case UINT_32 -> { var val = input.readInt(); if (val >= 0) { handleInt(val); } else { handleUnsignedLong(Integer.toUnsignedLong(val)); } } case UINT_64 -> handleUnsignedLong(input.readLong()); case SINT_8 -> handleInt((int) input.readByte()); case SINT_16 -> handleInt((int) input.readShort()); case SINT_32 -> handleInt(input.readInt()); case SINT_64 -> handleSignedLong(input.readLong()); case FIX_EXT_1 -> extension(1, true); case FIX_EXT_2 -> extension(2, true); case FIX_EXT_4 -> extension(4, true); case FIX_EXT_8 -> extension(8, true); case FIX_EXT_16 -> extension(16, true); case STR_8 -> string(input.readUnsignedByte()); case STR_16 -> string(input.readUnsignedShort()); case STR_32 -> string(input.readInt()); case ARRAY_16 -> array(input.readUnsignedShort()); case ARRAY_32 -> array(input.readInt()); case MAP_16 -> map(input.readUnsignedShort()); case MAP_32 -> map(input.readInt()); default -> handleUnknown(b); } } } private void string(int size) throws IOException { if (size < 0) { throw new IllegalStateException("String too large"); } var bytes = new byte[size]; input.readFully(bytes); var str = new String(bytes, UTF_8); handleString(str); } private void array(int size) throws IOException { handleArrayHeader(size); for (var i = 0; i < size; i++) { readArrayItem(); } } void readArrayItem() throws IOException { var next = input.readUnsignedByte(); readObject(next); } private void map(int size) throws IOException { handleMapHeader(size); for (var i = 0; i < size; i++) { readMapKey(); readMapValue(); } } void readMapKey() throws IOException { var next = input.readUnsignedByte(); readObject(next); } void readMapValue() throws IOException { var next = input.readUnsignedByte(); readObject(next); } private void binary(int size) throws IOException { if (size < 0) { throw new IllegalStateException("Binary too large"); } var bytes = new byte[size]; input.readFully(bytes); handleBinary(bytes); } private void extension(int size, boolean numeric) throws IOException { int type = input.readByte(); if (size < 0) { throw new IllegalStateException("Extension too large"); } var bytes = new byte[size]; input.readFully(bytes); handleExtension(type, numeric, bytes); } void handleObjectStart() { } void handleBoolean(boolean bool) { } void handleNil() { } void handleInt(int value) { } void handleUnsignedLong(long value) { } void handleSignedLong(long value) { } void handleFloat(float value) { } void handleDouble(double value) { } void handleUnknown(byte b) { } void handleString(String str) { } void handleArrayHeader(int size) { } void handleMapHeader(int size) { } void handleBinary(byte[] bytes) { } void handleExtension(int type, boolean numeric, byte[] bytes) { } //----------------------------------------------------------------------- /** * Skips over the next object in an input stream. * * @param input the input stream, not null * @throws IOException if an error occurs */ public static void skipObject(DataInputStream input) throws IOException { new Skipper(input).skip(input.readByte()); } private static class Skipper extends MsgPackInput { Skipper(DataInputStream input) { super(input); } void skip(int typeByte) throws IOException { readObject(typeByte); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/MsgPackOutput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Outputter for MsgPack data. */ final class MsgPackOutput extends MsgPack { /** * The stream to write to. */ private final DataOutputStream output; /** * Creates an instance. * * @param stream the stream to write to, not null */ MsgPackOutput(OutputStream stream) { this.output = new DataOutputStream(stream); } /** * Creates an instance. * * @param stream the stream to write to, not null */ MsgPackOutput(DataOutputStream stream) { this.output = stream; } //----------------------------------------------------------------------- /** * Writes a MessagePack nil. * * @throws IOException if an error occurs */ void writeNil() throws IOException { output.writeByte(NIL); } /** * Writes a MessagePack boolean. * * @param value the value * @throws IOException if an error occurs */ void writeBoolean(boolean value) throws IOException { if (value) { output.writeByte(TRUE); } else { output.writeByte(FALSE); } } /** * Writes a MessagePack int. * * @param value the value * @throws IOException if an error occurs */ void writeInt(int value) throws IOException { if (value < MIN_FIX_INT) { // large negative if (value >= Byte.MIN_VALUE) { output.writeByte(SINT_8); output.writeByte((byte) value); } else if (value >= Short.MIN_VALUE) { output.writeByte(SINT_16); output.writeShort((short) value); } else { output.writeByte(SINT_32); output.writeInt(value); } } else if (value < MAX_FIX_INT) { // in range -64 to 127 output.writeByte(value); } else { // large positive if (value < 0xFF) { output.writeByte(UINT_8); output.writeByte((byte) value); } else if (value < 0xFFFF) { output.writeByte(UINT_16); output.writeShort((short) value); } else { output.writeByte(UINT_32); output.writeInt(value); } } } /** * Writes a MessagePack long. * * @param value the value * @throws IOException if an error occurs */ void writeLong(long value) throws IOException { if (value < MIN_FIX_INT) { // large negative if (value >= Byte.MIN_VALUE) { output.writeByte(SINT_8); output.writeByte((byte) value); } else if (value >= Short.MIN_VALUE) { output.writeByte(SINT_16); output.writeShort((short) value); } else if (value >= Integer.MIN_VALUE) { output.writeByte(SINT_32); output.writeInt((int) value); } else { output.writeByte(SINT_64); output.writeLong(value); } } else if (value < MAX_FIX_INT) { // in range -64 to 127 output.writeByte((byte) value); } else { // large positive if (value < 0xFF) { output.writeByte(UINT_8); output.writeByte((byte) value); } else if (value < 0xFFFF) { output.writeByte(UINT_16); output.writeShort((short) value); } else if (value < 0xFFFFFFFFL) { output.writeByte(UINT_32); output.writeInt((int) value); } else { output.writeByte(UINT_64); output.writeLong(value); } } } /** * Writes a MessagePack float. * * @param value the value * @throws IOException if an error occurs */ void writeFloat(float value) throws IOException { output.writeByte(FLOAT_32); output.writeFloat(value); } /** * Writes a MessagePack double. * * @param value the value * @throws IOException if an error occurs */ void writeDouble(double value) throws IOException { output.writeByte(FLOAT_64); output.writeDouble(value); } /** * Writes a MessagePack byte block. * * @param bytes the bytes, not null * @throws IOException if an error occurs */ void writeBytes(byte[] bytes) throws IOException { var size = bytes.length; if (size < 256) { output.writeByte(BIN_8); output.writeByte(size); } else if (size < 65536) { output.writeByte(BIN_16); output.writeShort(size); } else { output.writeByte(BIN_32); output.writeInt(size); } output.write(bytes); } /** * Writes a MessagePack string. * * @param value the value * @throws IOException if an error occurs */ void writeString(String value) throws IOException { // Java 21 performance testing showed manually converting to UTF-8 to be slower var bytes = value.getBytes(UTF_8); var size = bytes.length; if (size < 32) { output.writeByte(MIN_FIX_STR + size); } else if (size < 256) { output.writeByte(STR_8); output.writeByte(size); } else { writeStringHeaderLarge(size); } output.write(bytes); } // separate out larger strings, which may benefit hotspot private void writeStringHeaderLarge(int size) throws IOException { if (size < 65536) { output.writeByte(STR_16); output.writeShort(size); } else { output.writeByte(STR_32); output.writeInt(size); } } /** * Writes a MessagePack array header. * * @param size the size * @throws IOException if an error occurs */ void writeArrayHeader(int size) throws IOException { if (size < 16) { output.writeByte(MIN_FIX_ARRAY + size); } else if (size < 65536) { output.writeByte(ARRAY_16); output.writeShort(size); } else { output.writeByte(ARRAY_32); output.writeInt(size); } } /** * Writes a MessagePack map header. * * @param size the size * @throws IOException if an error occurs */ void writeMapHeader(int size) throws IOException { if (size < 16) { output.writeByte(MIN_FIX_MAP + size); } else if (size < 65536) { output.writeByte(MAP_16); output.writeShort(size); } else { output.writeByte(MAP_32); output.writeInt(size); } } /** * Writes an extension value using FIX_EXT_1. * * @param extensionType the type * @param value the value to write as the data * @throws IOException if an error occurs */ void writeExtensionByte(int extensionType, int value) throws IOException { output.write(FIX_EXT_1); output.write(extensionType); output.write(value); } /** * Writes an extension string using EXT_8. * * @param extensionType the type * @param str the string to write as the data * @throws IOException if an error occurs */ void writeExtensionString(int extensionType, String str) throws IOException { var bytes = str.getBytes(UTF_8); if (bytes.length > 256) { throw new IllegalArgumentException("String too long"); } output.write(EXT_8); output.write(bytes.length); output.write(extensionType); output.write(bytes); } /** * Writes an extension reference of a positive integer using FIX_EXT data types. * * @param extensionType the type * @param reference the positive integer reference to write as the data * @throws IOException if an error occurs */ void writePositiveExtensionInt(int extensionType, int reference) throws IOException { if (reference < 0) { throw new IllegalArgumentException("Can only serialize positive references: " + reference); } if (reference < 0xFF) { output.write(FIX_EXT_1); output.write(extensionType); output.writeByte((byte) reference); } else if (reference < 0xFFFF) { output.writeByte(FIX_EXT_2); output.write(extensionType); output.writeShort((short) reference); } else { output.writeByte(FIX_EXT_4); output.write(extensionType); output.writeInt(reference); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/MsgPackVisualizer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; /** * Allows MsgPack data to be visualized. */ final class MsgPackVisualizer extends MsgPackInput { /** * The current indent. */ private String indent = ""; /** * The buffer. */ private final StringBuilder buf = new StringBuilder(1024); /** * Creates an instance. * * @param bytes the bytes to read, not null */ MsgPackVisualizer(byte[] bytes) { super(bytes); } /** * Creates an instance. * * @param stream the stream to read from, not null */ MsgPackVisualizer(InputStream stream) { super(stream); } /** * Creates an instance. * * @param stream the stream to read from, not null */ MsgPackVisualizer(DataInputStream stream) { super(stream); } //----------------------------------------------------------------------- /** * Visualizes the data in the stream. */ String visualizeData() { readAll(); return buf.toString(); } //----------------------------------------------------------------------- @Override void readArrayItem() throws IOException { indent = indent + "- "; super.readArrayItem(); indent = indent.substring(0, indent.length() - 2); } @Override void readMapKey() throws IOException { indent = indent + "= "; super.readMapKey(); indent = indent.substring(0, indent.length() - 2); } @Override void readMapValue() throws IOException { indent = indent + " "; super.readMapValue(); indent = indent.substring(0, indent.length() - 2); } @Override void handleObjectStart() { buf.append(indent); indent = indent.replace("-", " ").replace("=", " "); } @Override void handleBoolean(boolean bool) { buf.append(bool).append(System.lineSeparator()); } @Override void handleNil() { buf.append("nil").append(System.lineSeparator()); } @Override void handleInt(int value) { buf.append("int ").append(value).append(System.lineSeparator()); } @Override void handleUnsignedLong(long value) { buf.append("int ").append(value).append(" unsigned").append(System.lineSeparator()); } @Override void handleSignedLong(long value) { buf.append("int ").append(value).append(" signed").append(System.lineSeparator()); } @Override void handleFloat(float value) { buf.append("flt ").append(value).append(System.lineSeparator()); } @Override void handleDouble(double value) { buf.append("dbl ").append(value).append(System.lineSeparator()); } @Override void handleUnknown(byte b) { buf.append("Unknown - ").append(String.format("%02X ", b)).append(System.lineSeparator()); } @Override void handleString(String str) { buf.append("str '").append(str).append('\'').append(System.lineSeparator()); } @Override void handleArrayHeader(int size) { buf.append("arr (").append(size).append(")").append(System.lineSeparator()); } @Override void handleMapHeader(int size) { buf.append("map (").append(size).append(")").append(System.lineSeparator()); } @Override void handleBinary(byte[] bytes) { buf.append("bin '"); for (byte b : bytes) { buf.append(toHex(b)); } buf.append("'").append(System.lineSeparator()); } @Override void handleExtension(int type, boolean numeric, byte[] bytes) { String str; if (numeric) { var value = 0; for (byte b : bytes) { value = (value << 8) | (0xFF & b); } if (bytes.length == 1) { value = Byte.toUnsignedInt((byte) value); } else if (bytes.length == 2) { value = Short.toUnsignedInt((short) value); } str = Integer.toString(value); } else { str = new String(bytes, UTF_8); } buf.append("ext type=") .append(type) .append(" '") .append(str) .append("'"); switch (type) { case JODA_TYPE_BEAN -> buf.append(" (bean)"); case JODA_TYPE_DATA -> buf.append(" (data)"); case JODA_TYPE_META -> buf.append(" (meta)"); case JODA_TYPE_REF_KEY -> buf.append(" (refkey)"); case JODA_TYPE_REF -> buf.append(" (ref)"); default -> { } } buf.append(System.lineSeparator()); } } ================================================ FILE: src/main/java/org/joda/beans/ser/bin/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Serialization of Joda-Beans using a binary format. */ package org.joda.beans.ser.bin; ================================================ FILE: src/main/java/org/joda/beans/ser/json/AbstractJsonReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import static org.joda.beans.ser.json.JodaBeanJsonWriter.BEAN; import static org.joda.beans.ser.json.JodaBeanJsonWriter.META; import static org.joda.beans.ser.json.JodaBeanJsonWriter.TYPE; import static org.joda.beans.ser.json.JodaBeanJsonWriter.VALUE; import java.io.IOException; import java.io.UncheckedIOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.ResolvedType; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerCategory; import org.joda.beans.ser.SerIterable; import org.joda.beans.ser.SerIteratorFactory; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; /** * Provides the ability for a Joda-Bean to read from JSON. *

* The JSON format is defined by {@link JodaBeanJsonWriter}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ abstract class AbstractJsonReader { /** * Settings. */ private final JodaBeanSer settings; /** * The reader. */ private JsonInput input; /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map> knownTypes = new HashMap<>(); /** * Creates an instance. * * @param settings the settings, not null */ AbstractJsonReader(final JodaBeanSer settings) { JodaBeanUtils.notNull(settings, "settings"); this.settings = settings; } //----------------------------------------------------------------------- /** * Parses the root bean. * * @param input the JSON input * @param declaredType the declared type, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ T parseRoot(JsonInput input, Class declaredType) { try { this.input = input; var parsed = parseObject(input.acceptEvent(JsonEvent.OBJECT), declaredType, null, null, null, true); return declaredType.cast(parsed); } catch (ClassNotFoundException | ClassCastException ex) { throw new IllegalArgumentException(ex); } catch (IOException ex) { throw new UncheckedIOException(ex); } } // parse a bean, event after object start passed in private Object parseBean(JsonEvent event, Class beanType) throws IOException { var propName = ""; try { var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); var builder = deser.createBuilder(beanType, metaBean); while (event != JsonEvent.OBJECT_END) { // property name propName = input.acceptObjectKey(event); var metaProp = deser.findMetaProperty(beanType, metaBean, propName); // ignore unknown properties if (metaProp == null || metaProp.style().isDerived()) { input.skipData(); } else { var value = parseObject(input.readEvent(), SerOptional.extractType(metaProp, beanType), metaProp, beanType, null, false); deser.setValue(builder, metaProp, SerOptional.wrapValue(metaProp, beanType, value)); } propName = ""; event = input.acceptObjectSeparator(); } return deser.build(beanType, builder); } catch (IOException ex) { throw ex; } catch (Exception ex) { throw new IllegalArgumentException( "Error parsing bean: " + beanType.getName() + "::" + propName + ": " + ex.getMessage(), ex); } } // parse object, event passed in private Object parseObject( JsonEvent event, Class inputDeclaredType, MetaProperty metaProp, Class beanType, SerIterable parentIterable, boolean rootType) throws IOException, ClassNotFoundException { // avoid nulls var declaredType = (inputDeclaredType == null ? Object.class : inputDeclaredType); // establish type if (event == JsonEvent.OBJECT) { event = input.readEvent(); if (event == JsonEvent.STRING) { var key = input.parseObjectKey(); if (key.equals(BEAN)) { return parseTypedBean(declaredType, rootType); } else if (key.equals(TYPE)) { return parseTypedSimple(declaredType); } else if (key.equals(META)) { return parseTypedMeta(); } else { input.pushBack('"'); input.pushBackObjectKey(key); event = JsonEvent.OBJECT; } } else if (event == JsonEvent.OBJECT_END) { input.pushBack('}'); event = JsonEvent.OBJECT; } else { throw new IllegalArgumentException("Invalid JSON data: Expected JSON object end but found " + event); } } // parse based on type if (Bean.class.isAssignableFrom(declaredType)) { if (event == JsonEvent.OBJECT) { return parseBean(input.readEvent(), declaredType); } else { return parseSimple(event, declaredType); } } else { if (event == JsonEvent.OBJECT || event == JsonEvent.ARRAY) { SerIterable childIterable = null; if (metaProp != null) { childIterable = settings.getIteratorFactory().createIterable(metaProp, beanType, true); } else if (parentIterable != null) { childIterable = settings.getIteratorFactory().createIterable(parentIterable); } if (childIterable == null) { if (event == JsonEvent.ARRAY) { childIterable = parseUnknownArray(declaredType); } else { childIterable = parseUnknownObject(declaredType); } } return parseIterable(event, childIterable); } else { return parseSimple(event, declaredType); } } } // leniently assume it is am array/List (previously only the simple JSON parser made this assumption) SerIterable parseUnknownArray(Class declaredType) { if (declaredType.isArray()) { return SerIteratorFactory.array(declaredType.getComponentType()); } else { return SerIteratorFactory.list(Object.class, Collections.emptyList()); } } // leniently assume it is a Map (previously only the simple JSON parser made this assumption) SerIterable parseUnknownObject(Class declaredType) { return SerIteratorFactory.map(String.class, Object.class, Collections.emptyList()); } private Object parseTypedBean(Class declaredType, boolean rootType) throws IOException, ClassNotFoundException { var typeStr = input.acceptString(); Class effectiveType = SerTypeMapper.decodeType(typeStr, settings, basePackage, knownTypes); if (rootType) { if (!Bean.class.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Root type is not a Joda-Bean: " + effectiveType.getName()); } basePackage = effectiveType.getPackage().getName() + "."; } if (!declaredType.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Specified type is incompatible with declared type: " + declaredType.getName() + " and " + effectiveType.getName()); } var event = input.readEvent(); if (event == JsonEvent.COMMA) { event = input.readEvent(); } return parseBean(event, effectiveType); } private Object parseTypedSimple(Class declaredType) throws IOException, ClassNotFoundException { var typeStr = input.acceptString(); var effectiveType = settings.getDeserializers().decodeType(typeStr, settings, basePackage, knownTypes, declaredType); if (!declaredType.isAssignableFrom(effectiveType)) { if (!declaredType.isPrimitive() || ResolvedType.of(declaredType).toBoxed().getRawType() != effectiveType) { throw new IllegalArgumentException("Specified type is incompatible with declared type: " + declaredType.getName() + " and " + effectiveType.getName()); } } input.acceptEvent(JsonEvent.COMMA); var valueKey = input.acceptObjectKey(input.readEvent()); if (!valueKey.equals(VALUE)) { throw new IllegalArgumentException("Invalid JSON data: Expected 'value' key but found " + valueKey); } var result = parseSimple(input.readEvent(), effectiveType); input.acceptEvent(JsonEvent.OBJECT_END); return result; } private Object parseTypedMeta() throws IOException, ClassNotFoundException { var metaType = input.acceptString(); var childIterable = settings.getIteratorFactory().createIterable(metaType, settings, knownTypes); input.acceptEvent(JsonEvent.COMMA); var valueKey = input.acceptObjectKey(input.readEvent()); if (!valueKey.equals(VALUE)) { throw new IllegalArgumentException("Invalid JSON data: Expected 'value' key but found " + valueKey); } var result = parseIterable(input.readEvent(), childIterable); input.acceptEvent(JsonEvent.OBJECT_END); return result; } private Object parseIterable(JsonEvent event, SerIterable iterable) throws IOException, ClassNotFoundException { if (iterable.category() == SerCategory.MAP) { return parseIterableMap(event, iterable); } else if (iterable.category() == SerCategory.COUNTED) { return parseIterableCounted(event, iterable); } else if (iterable.category() == SerCategory.TABLE) { return parseIterableTable(event, iterable); } else if (iterable.category() == SerCategory.GRID) { return parseIterableGrid(event, iterable); } else { return parseIterableArray(event, iterable); } } private Object parseIterableMap(JsonEvent event, SerIterable iterable) throws IOException, ClassNotFoundException { if (event == JsonEvent.OBJECT) { event = input.readEvent(); while (event != JsonEvent.OBJECT_END) { var keyStr = input.acceptObjectKey(event); var key = parseText(keyStr, iterable.keyType()); var value = parseObject(input.readEvent(), iterable.valueType(), null, null, iterable, false); iterable.add(key, null, value, 1); event = input.acceptObjectSeparator(); } } else if (event == JsonEvent.ARRAY) { event = input.readEvent(); while (event != JsonEvent.ARRAY_END) { input.ensureEvent(event, JsonEvent.ARRAY); var key = parseObject(input.readEvent(), iterable.keyType(), null, null, null, false); input.acceptEvent(JsonEvent.COMMA); var value = parseObject(input.readEvent(), iterable.valueType(), null, null, iterable, false); input.acceptEvent(JsonEvent.ARRAY_END); iterable.add(key, null, value, 1); event = input.acceptArraySeparator(); } return iterable.build(); } else { throw new IllegalArgumentException("Invalid JSON data: Expected array or object but found " + event); } return iterable.build(); } private Object parseIterableTable(JsonEvent event, SerIterable iterable) throws IOException, ClassNotFoundException { input.ensureEvent(event, JsonEvent.ARRAY); event = input.readEvent(); while (event != JsonEvent.ARRAY_END) { input.ensureEvent(event, JsonEvent.ARRAY); var key = parseObject(input.readEvent(), iterable.keyType(), null, null, null, false); input.acceptEvent(JsonEvent.COMMA); var column = parseObject(input.readEvent(), iterable.columnType(), null, null, null, false); input.acceptEvent(JsonEvent.COMMA); var value = parseObject(input.readEvent(), iterable.valueType(), null, null, iterable, false); iterable.add(key, column, value, 1); input.acceptEvent(JsonEvent.ARRAY_END); event = input.acceptArraySeparator(); } return iterable.build(); } private Object parseIterableGrid(JsonEvent event, SerIterable iterable) throws IOException, ClassNotFoundException { input.ensureEvent(event, JsonEvent.ARRAY); input.acceptEvent(JsonEvent.NUMBER_INTEGRAL); var rows = (int) input.parseNumberIntegral(); input.acceptEvent(JsonEvent.COMMA); input.acceptEvent(JsonEvent.NUMBER_INTEGRAL); var columns = (int) input.parseNumberIntegral(); iterable.dimensions(new int[] {rows, columns}); event = input.acceptArraySeparator(); while (event != JsonEvent.ARRAY_END) { input.ensureEvent(event, JsonEvent.ARRAY); input.acceptEvent(JsonEvent.NUMBER_INTEGRAL); var row = (int) input.parseNumberIntegral(); input.acceptEvent(JsonEvent.COMMA); input.acceptEvent(JsonEvent.NUMBER_INTEGRAL); var column = (int) input.parseNumberIntegral(); input.acceptEvent(JsonEvent.COMMA); var value = parseObject(input.readEvent(), iterable.valueType(), null, null, iterable, false); input.acceptEvent(JsonEvent.ARRAY_END); iterable.add(row, column, value, 1); event = input.acceptArraySeparator(); } return iterable.build(); } private Object parseIterableCounted(JsonEvent event, SerIterable iterable) throws IOException, ClassNotFoundException { input.ensureEvent(event, JsonEvent.ARRAY); event = input.readEvent(); while (event != JsonEvent.ARRAY_END) { input.ensureEvent(event, JsonEvent.ARRAY); var value = parseObject(input.readEvent(), iterable.valueType(), null, null, iterable, false); input.acceptEvent(JsonEvent.COMMA); input.acceptEvent(JsonEvent.NUMBER_INTEGRAL); iterable.add(null, null, value, (int) input.parseNumberIntegral()); input.acceptEvent(JsonEvent.ARRAY_END); event = input.acceptArraySeparator(); } return iterable.build(); } private Object parseIterableArray(JsonEvent event, SerIterable iterable) throws IOException, ClassNotFoundException { input.ensureEvent(event, JsonEvent.ARRAY); event = input.readEvent(); while (event != JsonEvent.ARRAY_END) { var value = parseObject(event, iterable.valueType(), null, null, iterable, false); iterable.add(null, null, value, 1); event = input.acceptArraySeparator(); } return iterable.build(); } private Object parseSimple(JsonEvent event, Class type) throws IOException { switch (event) { case STRING: { var text = input.parseString(); return parseText(text, type); } case NUMBER_INTEGRAL: { var value = input.parseNumberIntegral(); if (type == Long.class || type == long.class) { return Long.valueOf(value); } else if (type == Short.class || type == short.class) { if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { throw new IllegalArgumentException("Invalid JSON data: Expected short, but was " + value); } return Short.valueOf((short) value); } else if (type == Byte.class || type == byte.class) { if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { throw new IllegalArgumentException("Invalid JSON data: Expected byte, but was " + value); } return Byte.valueOf((byte) value); } else if (type == Double.class || type == double.class) { double dblVal = value; if (value != (long) dblVal) { throw new IllegalArgumentException("Invalid JSON data: Value exceeds capacity of double: " + value); } return Double.valueOf(dblVal); } else if (type == Float.class || type == float.class) { float fltVal = value; if (value != (long) fltVal) { throw new IllegalArgumentException("Invalid JSON data: Value exceeds capacity of float: " + value); } return Float.valueOf(fltVal); } else if (type == Integer.class || type == int.class) { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid JSON data: Expected int, but was " + value); } return Integer.valueOf((int) value); } else { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { return Long.valueOf(value); } return Integer.valueOf((int) value); } } case NUMBER_FLOATING: { var value = input.parseNumberFloating(); if (type == Float.class || type == float.class) { return Float.valueOf((float) value); } else { return Double.valueOf(value); } } case NULL: { if (type == double.class || type == Double.class) { return Double.NaN; // leniently accept null for NaN } else if (type == float.class || type == Float.class) { return Float.NaN; // leniently accept null for NaN } else { return null; } } case TRUE: return Boolean.TRUE; case FALSE: return Boolean.FALSE; default: throw new IllegalArgumentException("Invalid JSON data: Expected simple type but found " + event); } } private Object parseText(String text, Class type) { if (type == Object.class || type.isAssignableFrom(String.class)) { return text; } return settings.getConverter().convertFromString(type, text); } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JodaBeanJsonNumberFormat.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; /** * Provides control over the format of unusual JSON numeric values. * * @since 3.0.0 */ public enum JodaBeanJsonNumberFormat { /** * Format using {@code NAN_AS_NULL} when using simple JSON, and {@code STRINGS} when using normal JSON. */ COMPATIBLE_V2, /** * Format NaN as {@code null} and Infinity as a string. *

* The value will be sent as literal {@code null}, the string {@code "Infinity"} or the string {@code "-Infinity"}. */ NAN_AS_NULL, /** * Format NaN and Infinity as a string. *

* The value will be sent as the string {@code "NaN"}, {@code "Infinity"} or {@code "-Infinity"}. */ STRING, /** * Format NaN and Infinity as a literal, as per 'The JSON5 Data Interchange Format'. *

* The value will be sent as the literal {@code NaN}, {@code Infinity} or {@code -Infinity}. */ LITERAL; } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JodaBeanJsonReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.Reader; import java.io.StringReader; import java.io.UncheckedIOException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.ser.JodaBeanSer; /** * Provides the ability for a Joda-Bean to read from JSON. *

* The JSON format is defined by {@link JodaBeanJsonWriter}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ public class JodaBeanJsonReader extends AbstractJsonReader { /** * Creates an instance. * * @param settings the settings, not null */ public JodaBeanJsonReader(JodaBeanSer settings) { super(settings); } //----------------------------------------------------------------------- /** * Reads and parses to a bean. * * @param input the input string, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ public Bean read(String input) { return read(input, Bean.class); } /** * Reads and parses to a bean. * * @param the root type * @param input the input string, not null * @param rootType the root type, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ public T read(String input, Class rootType) { JodaBeanUtils.notNull(input, "input"); return read(new StringReader(input), rootType); } /** * Reads and parses to a bean. * * @param input the input reader, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ public Bean read(Reader input) { return read(input, Bean.class); } /** * Reads and parses to a bean. * * @param the root type * @param input the input reader, not null * @param rootType the root type, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ public T read(Reader input, Class rootType) { JodaBeanUtils.notNull(input, "input"); JodaBeanUtils.notNull(rootType, "rootType"); var jsonInput = new JsonInput(input); return parseRoot(jsonInput, rootType); } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JodaBeanJsonWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.IOException; import java.lang.reflect.Array; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.ResolvedType; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTypeMapper; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableGrid; import org.joda.convert.ToStringConverter; import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.SetMultimap; import com.google.common.collect.Table; /** * Provides the ability for a Joda-Bean to be written to JSON. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. *

* The JSON format is kept relatively natural, however some meta-data is added. * This has the unfortunate effect of adding an additional object structure to * hold the type in a few places. *

* Beans are output using JSON objects where the key is the property name. * The type of the bean will be sent using the '@type' property name if necessary. *

* Most simple types, defined by Joda-Convert, are output as JSON strings. * If the simple type requires additional type information, the value is replaced by * a JSON object containing the keys '@type' and 'value'. *

* Null values are generally omitted, but where included are sent as 'null'. * Boolean values are sent as 'true' and 'false'. * Integer and Double values are sent as JSON numbers. * Other numeric types are also sent as numbers but may have additional type information. *

* Collections are output using JSON objects or arrays. * Multisets are output as a map of value to count. *

* If a collection contains a collection then addition meta-type information is * written to aid with deserialization. * At this level, the data read back may not be identical to that written. * If the collection type requires additional type information, the value is replaced by * a JSON object containing the keys '@meta' and 'value'. *

* Type names are shortened by the package of the root type if possible. * Certain basic types are also handled, such as String, Integer, File and URI. */ public class JodaBeanJsonWriter { /** * JSON bean type attribute. */ static final String BEAN = "@bean"; /** * JSON simple type attribute. */ static final String TYPE = "@type"; /** * JSON meta-type attribute. */ static final String META = "@meta"; /** * JSON value attribute. */ static final String VALUE = "value"; // why is there an ugly ClassValue setup here? // because this is O(1) whereas switch with pattern match which is O(n) private static final ClassValue> LOOKUP = new ClassValue<>() { @SuppressWarnings("rawtypes") // sneaky use of raw type to allow typed value in each method below @Override protected JsonHandler computeValue(Class type) { if (Bean.class.isAssignableFrom(type)) { return (JsonHandler) JodaBeanJsonWriter::writeBeanMaybeSimple; } if (type == String.class) { return (writer, declaredType, propName, value) -> writer.output.writeString((String) value); } if (type == Long.class || type == long.class) { return (writer, declaredType, propName, value) -> writer.writeLong(declaredType, (Long) value); } if (type == Integer.class || type == int.class) { return (writer, declaredType, propName, value) -> writer.output.writeInt((Integer) value); } if (type == Short.class || type == short.class) { return (writer, declaredType, propName, value) -> writer.writeShort(declaredType, (Short) value); } if (type == Byte.class || type == byte.class) { return (writer, declaredType, propName, value) -> writer.writeByte(declaredType, (Byte) value); } if (type == Double.class || type == double.class) { return (writer, declaredType, propName, value) -> writer.writeDouble(declaredType, (Double) value); } if (type == Float.class || type == float.class) { return (writer, declaredType, propName, value) -> writer.writeFloat(declaredType, (Float) value); } if (type == Boolean.class || type == boolean.class) { return (writer, declaredType, propName, value) -> writer.output.writeBoolean((Boolean) value); } return BaseJsonHandlers.INSTANCE.computeValue(type); } }; /** * The settings to use. */ final JodaBeanSer settings; // CSIGNORE /** * The outputter. */ JsonOutput output; // CSIGNORE /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map, String> knownTypes = new HashMap<>(); /** * Creates an instance. * * @param settings the settings to use, not null */ public JodaBeanJsonWriter(JodaBeanSer settings) { // COMPATIBLE_V2 value is eliminated here and in the subclass JodaBeanUtils.notNull(settings, "settings"); if (settings.getJsonNumberFormat() == JodaBeanJsonNumberFormat.COMPATIBLE_V2) { this.settings = settings.withJsonNumberFormat(JodaBeanJsonNumberFormat.STRING); } else { this.settings = settings; } } //----------------------------------------------------------------------- /** * Writes the bean to a string. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @return the JSON, not null */ public String write(Bean bean) { return write(bean, true); } /** * Writes the bean to a string specifying whether to include the type at the root. * * @param bean the bean to output, not null * @param includeRootType true to output the root type * @return the JSON, not null */ public String write(Bean bean, boolean includeRootType) { var buf = new StringBuilder(1024); try { write(bean, includeRootType, buf); } catch (IOException ex) { throw new IllegalStateException(ex); } return buf.toString(); } /** * Writes the bean to the {@code Appendable}. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @param output the output appendable, not null * @throws IOException if an error occurs */ public void write(Bean bean, Appendable output) throws IOException { write(bean, true, output); } /** * Writes the bean to the {@code Appendable} specifying whether to include the type at the root. * * @param bean the bean to output, not null * @param includeRootType true to output the root type * @param output the output appendable, not null * @throws IOException if an error occurs */ public void write(Bean bean, boolean includeRootType, Appendable output) throws IOException { JodaBeanUtils.notNull(bean, "bean"); JodaBeanUtils.notNull(output, "output"); this.output = new JsonOutput(output, settings.getJsonNumberFormat(), settings.getIndent(), settings.getNewLine()); var rootType = includeRootType ? ResolvedType.OBJECT : ResolvedType.of(bean.getClass()); // root always outputs the bean, not Joda-Convert form writeBean(rootType, bean, includeRootType); output.append(settings.getNewLine()); } //----------------------------------------------------------------------- // walk an object, by determining the runtime type void writeObject(ResolvedType declaredType, String propertyName, Object value) throws IOException { if (value == null) { output.writeNull(); } else { var handler = LOOKUP.get(value.getClass()); handler.handle(this, declaredType, propertyName, value); } } //------------------------------------------------------------------------- // writes a bean, favouring output as a Joda-Convert type private void writeBeanMaybeSimple(ResolvedType declaredType, String propertyName, Bean bean) throws IOException { // check for Joda-Convert cannot be in ClassValue as it relies on the settings if (settings.getConverter().isConvertible(bean.getClass())) { writeSimple(declaredType, propertyName, bean); } else { writeBean(declaredType, bean, false); } } // writes a bean, with meta type information if necessary private void writeBean(ResolvedType declaredType, Bean bean, boolean isRoot) throws IOException { output.writeObjectStart(); writeBeanType(declaredType, bean, isRoot); writeBeanProperties(declaredType, bean); output.writeObjectEnd(); } // optionally writes the type of the bean void writeBeanType(ResolvedType declaredType, Bean bean, boolean includeRootType) throws IOException { if (bean.getClass() != declaredType.getRawType()) { var typeStr = SerTypeMapper.encodeType(bean.getClass(), settings, basePackage, knownTypes); if (includeRootType) { basePackage = bean.getClass().getPackage().getName() + "."; } output.writeObjectKeyValue(BEAN, typeStr); } } // optionally writes the type of the bean private void writeBeanProperties(ResolvedType declaredType, Bean bean) throws IOException { for (var metaProperty : bean.metaBean().metaPropertyIterable()) { if (settings.isSerialized(metaProperty)) { var value = metaProperty.get(bean); if (value != null) { var resolvedType = metaProperty.propertyResolvedType(bean.getClass()); var handler = LOOKUP.get(value.getClass()); handler.handleProperty(this, resolvedType, metaProperty.name(), value); } } } } //------------------------------------------------------------------------- void writeLong(ResolvedType declaredType, Long val) throws IOException { if (declaredType.getRawType() == long.class) { output.writeLong(val); } else { output.writeObjectStart(); output.writeObjectKeyValue(TYPE, "Long"); output.writeObjectKey(VALUE); output.writeLong(val); output.writeObjectEnd(); } } void writeShort(ResolvedType declaredType, Short val) throws IOException { if (declaredType.getRawType() == short.class) { output.writeInt(val); } else { output.writeObjectStart(); output.writeObjectKeyValue(TYPE, "Short"); output.writeObjectKey(VALUE); output.writeInt(val); output.writeObjectEnd(); } } void writeByte(ResolvedType declaredType, Byte val) throws IOException { if (declaredType.getRawType() == byte.class) { output.writeInt(val); } else { output.writeObjectStart(); output.writeObjectKeyValue(TYPE, "Byte"); output.writeObjectKey(VALUE); output.writeInt(val); output.writeObjectEnd(); } } void writeDouble(ResolvedType declaredType, Double val) throws IOException { if (declaredType.getRawType() == double.class || (!Double.isNaN(val) && !Double.isInfinite(val))) { output.writeDouble(val); } else { output.writeObjectStart(); output.writeObjectKeyValue(TYPE, "Double"); output.writeObjectKey(VALUE); output.writeDouble(val); output.writeObjectEnd(); } } void writeFloat(ResolvedType declaredType, Float val) throws IOException { if (declaredType.getRawType() == float.class) { output.writeFloat(val); } else { output.writeObjectStart(); output.writeObjectKeyValue(TYPE, "Float"); output.writeObjectKey(VALUE); output.writeFloat(val); output.writeObjectEnd(); } } // writes a simple type void writeSimple(ResolvedType declaredType, String propertyName, Object value) throws IOException { // handle no declared type and subclasses Class realType = value.getClass(); Class effectiveType = declaredType.getRawType(); var requiresClose = false; if (effectiveType == Object.class) { if (realType != String.class) { effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); var typeStr = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); output.writeObjectStart(); output.writeObjectKeyValue(TYPE, typeStr); output.writeObjectKey(VALUE); requiresClose = true; } else { effectiveType = realType; } } else if (!settings.getConverter().isConvertible(effectiveType)) { effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); var typeStr = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); output.writeObjectStart(); output.writeObjectKeyValue(TYPE, typeStr); output.writeObjectKey(VALUE); requiresClose = true; } writeJodaConvert(declaredType, propertyName, value); // close open map if (requiresClose) { output.writeObjectEnd(); } } // writes using Joda-Convert void writeJodaConvert(ResolvedType declaredType, String propertyName, Object value) throws IOException { var realType = value.getClass(); try { var converted = settings.getConverter().convertToString(value); if (converted == null) { throw invalidNullString(propertyName, value); } output.writeString(converted); } catch (RuntimeException ex) { throw new IllegalArgumentException( "Unable to write property '" + propertyName + "', type " + realType.getName() + " could not be converted to a String", ex); } } private static IllegalArgumentException invalidNullString(String propertyName, Object value) { return new IllegalArgumentException( "Unable to write property '" + propertyName + "' because converter returned a null string: " + value); } // writes a map given map entries, code shared with Multimap void writeMapEntries( ResolvedType declaredType, String propertyName, Collection> mapEntries) throws IOException { // if key type is known and convertible use short key format, else use full bean format var keyType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var keyConverterOpt = settings.getConverter().converterFor(keyType.getRawType()); if (keyConverterOpt.isPresent()) { writeMapEntriesSimple(declaredType, propertyName, mapEntries, keyType, keyConverterOpt.get().withoutGenerics()); } else { writeMapComplex(declaredType, propertyName, mapEntries, keyType); } } private void writeMapEntriesSimple( ResolvedType declaredType, String propertyName, Collection> mapEntries, ResolvedType keyType, ToStringConverter keyConverter) throws IOException { var valueType = toWeakenedType(declaredType.getArgumentOrDefault(1)); output.writeObjectStart(); for (var entry : mapEntries) { var key = entry.getKey(); if (key == null) { throw invalidNullMapKey(propertyName); } var str = keyConverter.convertToString(key); if (str == null) { throw invalidConvertedNullMapKey(propertyName); } output.writeObjectKey(str); writeObject(valueType, "", entry.getValue()); } output.writeObjectEnd(); } private void writeMapComplex( ResolvedType declaredType, String propertyName, Collection> mapEntries, ResolvedType keyType) throws IOException { var valueType = toWeakenedType(declaredType.getArgumentOrDefault(1)); output.writeArrayStart(); for (var entry : mapEntries) { var key = entry.getKey(); if (key == null) { throw invalidNullMapKey(propertyName); } output.writeArrayItemStart(); output.writeArrayStart(); output.writeArrayItemStart(); writeObject(keyType, "", key); output.writeArrayItemStart(); writeObject(valueType, "", entry.getValue()); output.writeArrayEnd(); } output.writeArrayEnd(); } static IllegalArgumentException invalidNullMapKey(String propertyName) { return new IllegalArgumentException( "Unable to write property '" + propertyName + "', map key must not be null"); } static IllegalArgumentException invalidConvertedNullMapKey(String propertyName) { return new IllegalArgumentException( "Unable to write property '" + propertyName + "', converted map key must not be null"); } //------------------------------------------------------------------------- // gets the weakened type, which exists for backwards compatibility // once the parser can handle ResolvedType this method can, in theory, be removed static ResolvedType toWeakenedType(ResolvedType base) { for (var arg : base.getArguments()) { var rawType = arg.getRawType(); if (LOOKUP.get(rawType).isCollection()) { return base.toRaw(); } } return base; } //------------------------------------------------------------------------- // handler for meta types, but with IOException static interface MetaTypeHandler { public abstract String handle() throws IOException; } // handler for meta type content, but with IOException static interface ContentHandler { public abstract void handle() throws IOException; } // writes content with a meta type void writeWithMetaType(ContentHandler contentHandler, MetaTypeHandler metaTypeHandler) throws IOException { var metaTypeName = metaTypeHandler.handle(); if (metaTypeName != null) { output.writeObjectStart(); output.writeObjectKeyValue(META, metaTypeName); output.writeObjectKey(VALUE); contentHandler.handle(); output.writeObjectEnd(); } else { contentHandler.handle(); } } // writes content with a meta type void writeWithMetaType(ContentHandler contentHandler, Class cls, ResolvedType declaredType, String metaTypeName) throws IOException { if (!cls.isAssignableFrom(declaredType.getRawType())) { output.writeObjectStart(); output.writeObjectKeyValue(META, metaTypeName); output.writeObjectKey(VALUE); contentHandler.handle(); output.writeObjectEnd(); } else { contentHandler.handle(); } } //------------------------------------------------------------------------- private static interface JsonHandler { public abstract void handle( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, T obj) throws IOException; public default void handleProperty( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, T obj) throws IOException { writer.output.writeObjectKey(propertyName); handle(writer, declaredType, propertyName, obj); } public default boolean isCollection() { return false; } } private static interface CollectionJsonHandler extends JsonHandler { @Override public default boolean isCollection() { return true; } } //------------------------------------------------------------------------- private static sealed class BaseJsonHandlers { private static final BaseJsonHandlers INSTANCE = getInstance(); private static final BaseJsonHandlers getInstance() { try { ImmutableGrid.of(); // check if class is available return new CollectJsonHandlers(); } catch (RuntimeException | LinkageError ex) { try { ImmutableMultiset.of(); // check if class is available return new GuavaJsonHandlers(); } catch (RuntimeException | LinkageError ex2) { return new BaseJsonHandlers(); } } } @SuppressWarnings("rawtypes") // sneaky use of raw type to allow typed value in each method below JsonHandler computeValue(Class type) { if (type == Optional.class) { return OptionalJsonHandler.INSTANCE; } if (type.isArray()) { var componentType = type.getComponentType(); if (componentType.isPrimitive()) { if (componentType == byte.class) { return JodaBeanJsonWriter::writeSimple; } else { return (CollectionJsonHandler) BaseJsonHandlers::writePrimitiveArray; } } else { return (CollectionJsonHandler) BaseJsonHandlers::writeArray; } } if (Map.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) BaseJsonHandlers::writeMap; } if (Iterable.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) BaseJsonHandlers::writeCollection; } return JodaBeanJsonWriter::writeSimple; } // writes an array, with meta type information if necessary private static void writeArray( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Object[] array) throws IOException { var arrayComponentType = array.getClass().getComponentType(); // check actual type MetaTypeHandler metaTypeHandler = () -> { if (declaredType.getRawType() != array.getClass()) { return metaTypeArrayName(arrayComponentType); } return null; }; // write content ContentHandler contentHandler = () -> { var componentType = toWeakenedType(ResolvedType.of(arrayComponentType)); writer.output.writeArrayStart(); for (var item : array) { writer.output.writeArrayItemStart(); writer.writeObject(componentType, "", item); } writer.output.writeArrayEnd(); }; writer.writeWithMetaType(contentHandler, metaTypeHandler); } // writes a primitive array, with meta type information if necessary private static void writePrimitiveArray( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Object array) throws IOException { var arrayComponentType = array.getClass().getComponentType(); // check actual type MetaTypeHandler metaTypeHandler = () -> { if (declaredType.getRawType() != array.getClass()) { return metaTypeArrayName(arrayComponentType); } return null; }; // write content ContentHandler contentHandler = () -> { var componentType = ResolvedType.of(arrayComponentType); var handler = JodaBeanJsonWriter.LOOKUP.get(arrayComponentType); var arrayLength = Array.getLength(array); writer.output.writeArrayStart(); for (int i = 0; i < arrayLength; i++) { writer.output.writeArrayItemStart(); handler.handle(writer, componentType, propertyName, Array.get(array, i)); } writer.output.writeArrayEnd(); }; writer.writeWithMetaType(contentHandler, metaTypeHandler); } // determines the meta type name to use private static String metaTypeArrayName(Class valueType) { if (valueType.isArray()) { return metaTypeArrayName(valueType.getComponentType()) + "[]"; } if (valueType == Object.class) { return "Object[]"; } if (valueType == String.class) { return "String[]"; } return valueType.getName() + "[]"; } // writes a collection private static void writeCollection( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Iterable coll) throws IOException { // check actual type MetaTypeHandler metaTypeHandler = () -> { if (coll instanceof Set && !Set.class.isAssignableFrom(declaredType.getRawType())) { return "Set"; } else if (coll instanceof List && !List.class.isAssignableFrom(declaredType.getRawType())) { return "List"; } else if (!Collection.class.isAssignableFrom(declaredType.getRawType())) { return "Collection"; } return null; }; // write content, using an array ContentHandler contentHandler = () -> { var itemType = toWeakenedType(declaredType.getArgumentOrDefault(0)); writer.output.writeArrayStart(); for (var item : coll) { writer.output.writeArrayItemStart(); writer.writeObject(itemType, "", item); } writer.output.writeArrayEnd(); }; writer.writeWithMetaType(contentHandler, metaTypeHandler); } // writes a map, with meta type information if necessary private static void writeMap( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Map map) throws IOException { // write content, using a map ContentHandler contentHandler = () -> writer.writeMapEntries(declaredType, propertyName, map.entrySet()); writer.writeWithMetaType(contentHandler, Map.class, declaredType, "Map"); } } //------------------------------------------------------------------------- private static sealed class GuavaJsonHandlers extends BaseJsonHandlers { @Override @SuppressWarnings("rawtypes") // sneaky use of raw type to allow typed value in each method below JsonHandler computeValue(Class type) { if (Multimap.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) GuavaJsonHandlers::writeMultimap; } if (Multiset.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) GuavaJsonHandlers::writeMultiset; } if (Table.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) GuavaJsonHandlers::writeTable; } if (BiMap.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) GuavaJsonHandlers::writeBiMap; } if (com.google.common.base.Optional.class.isAssignableFrom(type)) { return GuavaOptionalJsonHandler.INSTANCE; } return super.computeValue(type); } // writes a multimap private static void writeMultimap( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Multimap mmap) throws IOException { // check actual type MetaTypeHandler metaTypeHandler = () -> { if (mmap instanceof SetMultimap && !SetMultimap.class.isAssignableFrom(declaredType.getRawType())) { return "SetMultimap"; } else if (mmap instanceof ListMultimap && !ListMultimap.class.isAssignableFrom(declaredType.getRawType())) { return "ListMultimap"; } else if (!Multimap.class.isAssignableFrom(declaredType.getRawType())) { return "Multimap"; } return null; }; // write content, using a map ContentHandler contentHandler = () -> writer.writeMapEntries(declaredType, propertyName, mmap.entries()); writer.writeWithMetaType(contentHandler, metaTypeHandler); } // writes a multiset private static void writeMultiset( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Multiset mset) throws IOException { // write content, using an array of value to count ContentHandler contentHandler = () -> { var valueType = toWeakenedType(declaredType.getArgumentOrDefault(0)); writer.output.writeArrayStart(); for (var entry : mset.entrySet()) { writer.output.writeArrayItemStart(); writer.output.writeArrayStart(); writer.output.writeArrayItemStart(); writer.writeObject(valueType, "", entry.getElement()); writer.output.writeArrayItemStart(); writer.output.writeInt(entry.getCount()); writer.output.writeArrayEnd(); } writer.output.writeArrayEnd(); }; writer.writeWithMetaType(contentHandler, Multiset.class, declaredType, "Multiset"); } // writes a table private static void writeTable( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Table table) throws IOException { // write content, using an array of cells ContentHandler contentHandler = () -> { var rowType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var columnType = toWeakenedType(declaredType.getArgumentOrDefault(1)); var valueType = toWeakenedType(declaredType.getArgumentOrDefault(2)); writer.output.writeArrayStart(); for (var cell : table.cellSet()) { writer.output.writeArrayItemStart(); writer.output.writeArrayStart(); writer.output.writeArrayItemStart(); writer.writeObject(rowType, "", cell.getRowKey()); writer.output.writeArrayItemStart(); writer.writeObject(columnType, "", cell.getColumnKey()); writer.output.writeArrayItemStart(); writer.writeObject(valueType, "", cell.getValue()); writer.output.writeArrayEnd(); } writer.output.writeArrayEnd(); }; writer.writeWithMetaType(contentHandler, Table.class, declaredType, "Table"); } // writes a BiMap, with meta type information if necessary private static void writeBiMap( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, BiMap biMap) throws IOException { MetaTypeHandler metaTypeHandler = () -> { if (!BiMap.class.isAssignableFrom(declaredType.getRawType())) { // hack around Guava annoyance by assuming that size 0 and 1 ImmutableBiMap // was actually meant to be an ImmutableMap if ((declaredType.getRawType() != Map.class && declaredType.getRawType() != ImmutableMap.class) || biMap.size() >= 2) { return "BiMap"; } else if (!Map.class.isAssignableFrom(declaredType.getRawType())) { return "Map"; } } return null; }; ContentHandler contentHandler = () -> writer.writeMapEntries(declaredType, propertyName, biMap.entrySet()); writer.writeWithMetaType(contentHandler, metaTypeHandler); } } //------------------------------------------------------------------------- private static final class CollectJsonHandlers extends GuavaJsonHandlers { @Override @SuppressWarnings("rawtypes") // sneaky use of raw type to allow typed value in each method below JsonHandler computeValue(Class type) { if (Grid.class.isAssignableFrom(type)) { return (CollectionJsonHandler>) CollectJsonHandlers::writeGrid; } return super.computeValue(type); } private static void writeGrid( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Grid grid) throws IOException { // write grid using sparse approach ContentHandler contentHandler = () -> { var valueType = toWeakenedType(declaredType.getArgumentOrDefault(0)); writer.output.writeArrayStart(); writer.output.writeArrayItemStart(); writer.output.writeInt(grid.rowCount()); writer.output.writeArrayItemStart(); writer.output.writeInt(grid.columnCount()); for (var cell : grid.cells()) { writer.output.writeArrayItemStart(); writer.output.writeArrayStart(); writer.output.writeArrayItemStart(); writer.output.writeInt(cell.getRow()); writer.output.writeArrayItemStart(); writer.output.writeInt(cell.getColumn()); writer.output.writeArrayItemStart(); writer.writeObject(valueType, "", cell.getValue()); writer.output.writeArrayEnd(); } writer.output.writeArrayEnd(); }; writer.writeWithMetaType(contentHandler, Grid.class, declaredType, "Grid"); } } //------------------------------------------------------------------------- static final class OptionalJsonHandler implements JsonHandler> { private static final OptionalJsonHandler INSTANCE = new OptionalJsonHandler(); // when Optional is not a property, it is processed as a kind of collection @Override public void handle( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Optional opt) throws IOException { var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.writeObject(valueType, "", opt.orElse(null)); } // when Optional is a property, it is ignored if empty @Override public void handleProperty( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, Optional opt) throws IOException { var value = opt.orElse(null); if (value != null) { var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.output.writeObjectKey(propertyName); writer.writeObject(valueType, propertyName, value); } } } //------------------------------------------------------------------------- static final class GuavaOptionalJsonHandler implements JsonHandler> { private static final GuavaOptionalJsonHandler INSTANCE = new GuavaOptionalJsonHandler(); // when Optional is not a property, it is processed as a kind of collection @Override public void handle( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, com.google.common.base.Optional opt) throws IOException { var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.writeObject(valueType, "", opt.orNull()); } // when Optional is a property, it is ignored if empty @Override public void handleProperty( JodaBeanJsonWriter writer, ResolvedType declaredType, String propertyName, com.google.common.base.Optional opt) throws IOException { var value = opt.orNull(); if (value != null) { var valueType = declaredType.getArgumentOrDefault(0).toRaw(); writer.output.writeObjectKey(propertyName); writer.writeObject(valueType, propertyName, value); } } } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JodaBeanSimpleJsonReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.Reader; import java.io.StringReader; import java.io.UncheckedIOException; import org.joda.beans.JodaBeanUtils; import org.joda.beans.ser.JodaBeanSer; /** * Provides the ability for a Joda-Bean to read from JSON. *

* The JSON format is defined by {@link JodaBeanJsonWriter}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ public class JodaBeanSimpleJsonReader extends AbstractJsonReader { /** * Creates an instance. * * @param settings the settings, not null */ public JodaBeanSimpleJsonReader(JodaBeanSer settings) { super(settings); } //----------------------------------------------------------------------- /** * Reads and parses to a bean. * * @param the root type * @param input the input string, not null * @param rootType the root type, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ public T read(String input, Class rootType) { JodaBeanUtils.notNull(input, "input"); return read(new StringReader(input), rootType); } /** * Reads and parses to a bean. * * @param the root type * @param input the input reader, not null * @param rootType the root type, not null * @return the bean, not null * @throws UncheckedIOException if unable to read the stream * @throws IllegalArgumentException if unable to parse the JSON */ public T read(Reader input, Class rootType) { JodaBeanUtils.notNull(input, "input"); JodaBeanUtils.notNull(rootType, "rootType"); var jsonInput = new JsonInput(input); return parseRoot(jsonInput, rootType); } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JodaBeanSimpleJsonWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.IOException; import java.util.Collection; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.ResolvedType; import org.joda.beans.ser.JodaBeanSer; import org.joda.convert.ToStringConverter; /** * Provides the ability for a Joda-Bean to be written to a simple JSON format. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. *

* The JSON format used here is natural, with no meta-data. * As such, it may not be possible to write some objects or read the JSON data back in. *

* Beans are output using JSON objects where the key is the property name. * Most simple types, defined by Joda-Convert, are output as JSON strings. * Null values are generally omitted, but where included are sent as 'null'. * Boolean values are sent as 'true' and 'false'. * Numeric values are sent as JSON numbers. * Maps must have a key that can be converted to a string by Joda-Convert. * The property type needs to be known when writing/reading - properties, or * list/map entries, that are defined as {@code Object} are unlikely to work well. *

* Collections are output using JSON arrays. Maps as JSON objects. */ public class JodaBeanSimpleJsonWriter extends JodaBeanJsonWriter { /** * Creates an instance. * * @param settings the settings to use, not null */ public JodaBeanSimpleJsonWriter(JodaBeanSer settings) { super(adjustSettings(settings)); } private static JodaBeanSer adjustSettings(JodaBeanSer settings) { JodaBeanUtils.notNull(settings, "settings"); if (settings.getJsonNumberFormat() == JodaBeanJsonNumberFormat.COMPATIBLE_V2) { return settings.withJsonNumberFormat(JodaBeanJsonNumberFormat.NAN_AS_NULL); } else { return settings; } } //----------------------------------------------------------------------- /** * Writes the bean to a string. * * @param bean the bean to output, not null * @return the JSON, not null */ @Override public String write(Bean bean) { return super.write(bean); } /** * Writes the bean to the {@code Appendable}. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @param output the output appendable, not null * @throws IOException if an error occurs */ @Override public void write(Bean bean, Appendable output) throws IOException { super.write(bean, false, output); } //------------------------------------------------------------------------- @Override void writeBeanType(ResolvedType declaredType, Bean bean, boolean includeRootType) throws IOException { // do not write type } //------------------------------------------------------------------------- @Override void writeLong(ResolvedType declaredType, Long val) throws IOException { // do not write type output.writeLong(val); } @Override void writeShort(ResolvedType declaredType, Short val) throws IOException { // do not write type output.writeInt(val); } @Override void writeByte(ResolvedType declaredType, Byte val) throws IOException { // do not write type output.writeInt(val); } @Override void writeDouble(ResolvedType declaredType, Double val) throws IOException { // do not write type output.writeDouble(val); } @Override void writeFloat(ResolvedType declaredType, Float val) throws IOException { // do not write type output.writeFloat(val); } //------------------------------------------------------------------------- @Override void writeSimple(ResolvedType declaredType, String propertyName, Object value) throws IOException { // do not write type super.writeJodaConvert(declaredType, propertyName, value); } // writes a map given map entries, used by Map/Multimap/BiMap @Override void writeMapEntries( ResolvedType declaredType, String propertyName, Collection> mapEntries) throws IOException { // simple JSON requires the key to be a Joda-Convert type var keyType = toWeakenedType(declaredType.getArgumentOrDefault(0)); var valueType = toWeakenedType(declaredType.getArgumentOrDefault(1)); // converter based on the declared type if possible, else based on the runtime type var keyConverterOpt = settings.getConverter().converterFor(keyType.getRawType()); ToStringConverter keyConverter = keyConverterOpt.isPresent() ? keyConverterOpt.get().withoutGenerics() : key -> settings.getConverter().convertToString(key); output.writeObjectStart(); for (var entry : mapEntries) { var key = entry.getKey(); if (key == null) { throw invalidNullMapKey(propertyName); } var str = keyConverter.convertToString(key); if (str == null) { throw invalidConvertedNullMapKey(propertyName); } output.writeObjectKey(str); writeObject(valueType, "", entry.getValue()); } output.writeObjectEnd(); } //------------------------------------------------------------------------- // writes content with a meta type @Override void writeWithMetaType(ContentHandler contentHandler, MetaTypeHandler metaTypeHandler) throws IOException { // do not write type contentHandler.handle(); } @Override void writeWithMetaType(ContentHandler contentHandler, Class cls, ResolvedType declaredType, String metaTypeName) throws IOException { // do not write type contentHandler.handle(); } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JsonEvent.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; /** * JSON event types. */ enum JsonEvent { OBJECT, OBJECT_END, ARRAY, ARRAY_END, STRING, NUMBER_INTEGRAL, NUMBER_FLOATING, NULL, TRUE, FALSE, COMMA, COLON, } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JsonInput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.IOException; import java.io.Reader; /** * Reader of JSON data. */ final class JsonInput { // this code parses the literals NaN, Infinity, -Infinity, +Infinity // any number may be prefixed by + /** encoding JSON */ private static final String[] REPLACE = new String[128]; static { for (var i = 0; i < 32; i++) { REPLACE[i] = String.format("\\u%04x", i); } REPLACE['\b'] = "\\b"; REPLACE['\t'] = "\\t"; REPLACE['\n'] = "\\n"; REPLACE['\f'] = "\\f"; REPLACE['\r'] = "\\r"; REPLACE['"'] = "\\\""; REPLACE['\\'] = "\\\\"; REPLACE[127] = "\\u007f"; } /** * The reader. */ private final Reader input; /** * The reused string buffer. */ private final StringBuilder buf = new StringBuilder(32); /** * The last parsed integral number. */ private long integral; /** * The last parsed floating number. */ private double floating; /** * The previously read character. */ private Character cachedNext; /** * The previously read object key. */ private String cachedObjectKey; /** * Creates an instance that parses JSON. * * @param input the input to read from, not null */ JsonInput(Reader input) { this.input = input; } //----------------------------------------------------------------------- /** * Writes a JSON null. * * @throws IOException if an error occurs */ JsonEvent readEvent() throws IOException { var next = readNext(); // whitespace while (next == ' ' || next == '\t' || next == '\n' || next == '\r') { next = readNext(); } // identify token return switch (next) { case '{' -> JsonEvent.OBJECT; case '}' -> JsonEvent.OBJECT_END; case '[' -> JsonEvent.ARRAY; case ']' -> JsonEvent.ARRAY_END; case '"' -> JsonEvent.STRING; case '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> acceptNumber(next); case 'n' -> acceptNull(); case 't' -> acceptTrue(); case 'f' -> acceptFalse(); case 'N' -> acceptNaN(); case 'I' -> acceptInfinity(); case ',' -> JsonEvent.COMMA; case ':' -> JsonEvent.COLON; default -> throw new IllegalArgumentException("Invalid JSON data: Expected JSON character but found '" + next + "'"); }; } // store peeked value for later use void pushBack(char ch) { cachedNext = ch; } // store peeked value for later use void pushBackObjectKey(String objectKey) { cachedObjectKey = objectKey; } JsonEvent ensureEvent(JsonEvent event, JsonEvent expected) { if (event != expected) { throw new IllegalArgumentException("Invalid JSON data: Expected " + expected + " but found " + event); } return event; } JsonEvent acceptEvent(JsonEvent expected) throws IOException { return ensureEvent(readEvent(), expected); } //----------------------------------------------------------------------- // expect object key and parse it String acceptObjectKey(JsonEvent event) throws IOException { ensureEvent(event, JsonEvent.STRING); return parseObjectKey(); } // opening quite already consumed String parseObjectKey() throws IOException { if (cachedObjectKey != null) { var key = cachedObjectKey; cachedObjectKey = null; return key; } var str = parseString(); acceptEvent(JsonEvent.COLON); return str; } //----------------------------------------------------------------------- // expect string and parse it String acceptString() throws IOException { acceptEvent(JsonEvent.STRING); return parseString(); } // opening quite already consumed String parseString() throws IOException { buf.setLength(0); var next = readNext(); while (next != '"') { if (next == '\\') { parseEscape(); } else { buf.append(next); } next = readNext(); } return buf.toString(); } private void parseEscape() throws IOException { var next = readNext(); switch (next) { case '"': buf.append('"'); return; case '/': buf.append('/'); return; case '\\': buf.append('\\'); return; case 'b': buf.append('\b'); return; case 'f': buf.append('\f'); return; case 'n': buf.append('\n'); return; case 'r': buf.append('\r'); return; case 't': buf.append('\t'); return; case 'u': var total = 0; for (var i = 0; i < 4; i++) { total = total * 16 + acceptHex(); } buf.append((char) total); return; default: throw new IllegalArgumentException("Invalid JSON data: Expected valid escape sequence but found '\\" + next + "'"); } } private int acceptHex() throws IOException { var next = readNext(); if (next >= '0' && next <= '9') { return next - 48; } if (next >= 'a' && next <= 'f') { return next - 97 + 10; } if (next >= 'A' && next <= 'F') { return next - 65 + 10; } throw new IllegalArgumentException("Invalid JSON data: Expected hex but found '" + next + "'"); } //----------------------------------------------------------------------- // number already parsed long parseNumberIntegral() { return integral; } // number already parsed double parseNumberFloating() { return floating; } private JsonEvent acceptNumber(char first) throws IOException { buf.setLength(0); buf.append(first); var last = first; var next = readNext(); while ((next >= '0' && next <= '9') || next == '.' || next == '-' || next == '+' || next == 'e' || next == 'E' || next == 'I') { buf.append(next); last = next; next = readNext(); } pushBack(next); var str = buf.toString(); if (str.equals("-I")) { acceptInfinity(); floating = Double.NEGATIVE_INFINITY; return JsonEvent.NUMBER_FLOATING; } else if (str.equals("+I")) { return acceptInfinity(); } else if (last < '0' || last > '9') { throw new IllegalArgumentException("Invalid JSON data: Expected number but found invalid last char '" + last + "'"); } if (str.equals("0")) { integral = 0; return JsonEvent.NUMBER_INTEGRAL; } else if (str.startsWith("0") && str.charAt(1) != '.') { throw new IllegalArgumentException("Invalid JSON data: Expected number but found zero at start"); } else if (str.contains(".") || str.contains("e") || str.contains("E")) { floating = Double.parseDouble(str); return JsonEvent.NUMBER_FLOATING; } else { integral = Long.parseLong(str); return JsonEvent.NUMBER_INTEGRAL; } } //----------------------------------------------------------------------- private JsonEvent acceptNull() throws IOException { acceptChar('u'); acceptChar('l'); acceptChar('l'); return JsonEvent.NULL; } private JsonEvent acceptTrue() throws IOException { acceptChar('r'); acceptChar('u'); acceptChar('e'); return JsonEvent.TRUE; } private JsonEvent acceptFalse() throws IOException { acceptChar('a'); acceptChar('l'); acceptChar('s'); acceptChar('e'); return JsonEvent.FALSE; } private JsonEvent acceptNaN() throws IOException { acceptChar('a'); acceptChar('N'); floating = Double.NaN; return JsonEvent.NUMBER_FLOATING; } private JsonEvent acceptInfinity() throws IOException { acceptChar('n'); acceptChar('f'); acceptChar('i'); acceptChar('n'); acceptChar('i'); acceptChar('t'); acceptChar('y'); floating = Double.POSITIVE_INFINITY; return JsonEvent.NUMBER_FLOATING; } private void acceptChar(char ch) throws IOException { var next = readNext(); if (next != ch) { throw new IllegalArgumentException("Invalid JSON data: Expected '" + ch + "' but found '" + next + "'"); } } //----------------------------------------------------------------------- private char readNext() throws IOException { if (cachedNext != null) { var next = cachedNext.charValue(); cachedNext = null; return next; } var next = input.read(); if (next == -1) { throw new IllegalArgumentException("Invalid JSON data: End of file"); } return (char) next; } void skipData() throws IOException { skipData(readEvent()); } private void skipData(JsonEvent event) throws IOException { switch (event) { case OBJECT: { var ev = readEvent(); while (ev != JsonEvent.OBJECT_END) { acceptObjectKey(ev); skipData(); ev = acceptObjectSeparator(); } break; } case ARRAY: { var ev = readEvent(); while (ev != JsonEvent.ARRAY_END) { skipData(ev); ev = acceptArraySeparator(); } break; } case STRING: { parseString(); break; } case NULL: case TRUE: case FALSE: case NUMBER_FLOATING: case NUMBER_INTEGRAL: break; default: throw new IllegalArgumentException("Invalid JSON data: Expected data item but found " + event); } } //----------------------------------------------------------------------- // accepts a comma or object end JsonEvent acceptObjectSeparator() throws IOException { var event = readEvent(); if (event == JsonEvent.COMMA) { return readEvent(); // leniently allow comma before objectEnd } else { return ensureEvent(event, JsonEvent.OBJECT_END); } } // accepts a comma or array end JsonEvent acceptArraySeparator() throws IOException { var event = readEvent(); if (event == JsonEvent.COMMA) { return readEvent(); // leniently allow comma before arrayEnd } else { return ensureEvent(event, JsonEvent.ARRAY_END); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/JsonOutput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.IOException; import java.util.BitSet; /** * Outputter for JSON data. */ final class JsonOutput { /** encoding JSON */ private static final String[] REPLACE = new String[128]; static { // performance is better without adding the characters from 32 to 126 // (because they would have to be added as String, not char, which slows down the append method) for (var i = 0; i < 32; i++) { REPLACE[i] = String.format("\\u%04x", i); } REPLACE['\b'] = "\\b"; REPLACE['\t'] = "\\t"; REPLACE['\n'] = "\\n"; REPLACE['\f'] = "\\f"; REPLACE['\r'] = "\\r"; REPLACE['"'] = "\\\""; REPLACE['\\'] = "\\\\"; REPLACE[127] = "\\u007f"; } /** * The appender to write to. */ private final Appendable output; /** * The number format. */ private final JodaBeanJsonNumberFormat numberFormat; /** * The indent amount. */ private final String indent; /** * The new line. */ private final String newLine; /** * The current indent. */ private String currentIndent = ""; /** * The comma depth. */ private int commaDepth; /** * The comma state. */ private final BitSet commaState = new BitSet(64); /** * Creates an instance that outputs in compact format. * * @param output the output to write to, not null */ JsonOutput(Appendable output) { this(output, JodaBeanJsonNumberFormat.STRING, "", ""); } /** * Creates an instance where the output format can be controlled. * * @param output the output to write to, not null * @param numberFormat the number format, not null * @param indent the pretty format indent * @param newLine the pretty format new line */ JsonOutput(Appendable output, JodaBeanJsonNumberFormat numberFormat, String indent, String newLine) { this.output = output; this.numberFormat = numberFormat; this.indent = indent; this.newLine = newLine; } //----------------------------------------------------------------------- /** * Writes a JSON null. * * @throws IOException if an error occurs */ void writeNull() throws IOException { output.append("null"); } /** * Writes a JSON boolean. * * @param value the value * @throws IOException if an error occurs */ void writeBoolean(boolean value) throws IOException { if (value) { output.append("true"); } else { output.append("false"); } } //----------------------------------------------------------------------- /** * Writes a JSON int. * * @param value the value * @throws IOException if an error occurs */ void writeInt(int value) throws IOException { output.append(Integer.toString(value)); } /** * Writes a JSON long. * * @param value the value * @throws IOException if an error occurs */ void writeLong(long value) throws IOException { output.append(Long.toString(value)); } /** * Writes a JSON float. *

* This outputs the values of NaN, and Infinity as strings. * * @param value the value * @throws IOException if an error occurs */ void writeFloat(float value) throws IOException { if (Float.isNaN(value)) { switch (numberFormat) { case LITERAL -> output.append("NaN"); case NAN_AS_NULL -> writeNull(); default -> output.append("\"NaN\""); } } else if (Float.isInfinite(value)) { var str = value > 0 ? "Infinity" : "-Infinity"; switch (numberFormat) { case LITERAL -> output.append(str); default -> output.append('"').append(str).append('"'); } } else { output.append(Float.toString(value)); } } /** * Writes a JSON double. *

* This outputs the values of NaN, and Infinity as strings. * * @param value the value * @throws IOException if an error occurs */ void writeDouble(double value) throws IOException { if (Double.isNaN(value)) { switch (numberFormat) { case LITERAL -> output.append("NaN"); case NAN_AS_NULL -> writeNull(); default -> output.append("\"NaN\""); } } else if (Double.isInfinite(value)) { var str = value > 0 ? "Infinity" : "-Infinity"; switch (numberFormat) { case LITERAL -> output.append(str); default -> output.append('"').append(str).append('"'); } } else { output.append(Double.toString(value)); } } //----------------------------------------------------------------------- /** * Writes a JSON string. * * @param value the value * @throws IOException if an error occurs */ void writeString(String value) throws IOException { output.append('"'); for (var i = 0; i < value.length(); i++) { var ch = value.charAt(i); if (ch < 128) { var replace = REPLACE[ch]; if (replace != null) { output.append(replace); } else { output.append(ch); } } else if (ch == '\u2028') { output.append("\\u2028"); // match other JSON writers } else if (ch == '\u2029') { output.append("\\u2029"); // match other JSON writers } else { output.append(ch); } } output.append('"'); } //----------------------------------------------------------------------- /** * Writes a JSON array start. * * @throws IOException if an error occurs */ void writeArrayStart() throws IOException { output.append('['); commaDepth++; commaState.clear(commaDepth); } /** * Writes a JSON array item start. * * @throws IOException if an error occurs */ void writeArrayItemStart() throws IOException { if (commaState.get(commaDepth)) { output.append(','); if (!newLine.isEmpty()) { output.append(' '); } } else { commaState.set(commaDepth); } } /** * Writes a JSON array end. * * @throws IOException if an error occurs */ void writeArrayEnd() throws IOException { output.append(']'); commaDepth--; } //----------------------------------------------------------------------- /** * Writes a JSON object start. * * @throws IOException if an error occurs */ void writeObjectStart() throws IOException { output.append('{'); currentIndent = currentIndent + indent; commaDepth++; commaState.set(commaDepth, false); } /** * Writes a JSON object key. *

* This handles the comma, string encoded key and separator colon. * * @param key the item key * @throws IOException if an error occurs */ void writeObjectKey(String key) throws IOException { if (commaState.get(commaDepth)) { output.append(','); } else { commaState.set(commaDepth, true); } output.append(newLine); output.append(currentIndent); writeString(key); output.append(':'); if (!newLine.isEmpty()) { output.append(' '); } } /** * Writes a JSON object key and value. * * @param key the item key * @param value the item value * @throws IOException if an error occurs */ void writeObjectKeyValue(String key, String value) throws IOException { writeObjectKey(key); writeString(value); } /** * Writes a JSON object end. * * @throws IOException if an error occurs */ void writeObjectEnd() throws IOException { currentIndent = currentIndent.substring(0, currentIndent.length() - indent.length()); if (commaState.get(commaDepth)) { output.append(newLine); output.append(currentIndent); } output.append('}'); commaDepth--; } } ================================================ FILE: src/main/java/org/joda/beans/ser/json/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Serialization of Joda-Beans using JSON. */ package org.joda.beans.ser.json; ================================================ FILE: src/main/java/org/joda/beans/ser/map/JodaBeanSimpleMapReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.map; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerIterable; import org.joda.beans.ser.SerIteratorFactory; import org.joda.beans.ser.SerOptional; /** * Provides the ability for a Joda-Bean to read from a JSON-like in memory {@code Map}. *

* The format is defined by {@link JodaBeanSimpleMapWriter}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ public class JodaBeanSimpleMapReader { /** * Settings. */ private final JodaBeanSer settings; /** * Creates an instance. * * @param settings the settings, not null */ public JodaBeanSimpleMapReader(JodaBeanSer settings) { JodaBeanUtils.notNull(settings, "settings"); this.settings = settings; } //----------------------------------------------------------------------- /** * Reads and parses to a bean. * * @param the root type * @param input the map input, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(Map input, Class rootType) { JodaBeanUtils.notNull(input, "input"); JodaBeanUtils.notNull(rootType, "rootType"); try { return parseRoot(input, rootType); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } //----------------------------------------------------------------------- /** * Parses the root bean. * * @param input the map input, not null * @param declaredType the declared type, not null * @return the bean, not null * @throws Exception if an error occurs */ private T parseRoot(Map input, Class declaredType) { var parsed = parseBean(input, declaredType); return declaredType.cast(parsed); } // parse a bean, event after object start passed in private Object parseBean(Map input, Class beanType) { var propName = ""; try { var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); var builder = deser.createBuilder(beanType, metaBean); for (var entry : input.entrySet()) { // property name propName = entry.getKey(); var metaProp = deser.findMetaProperty(beanType, metaBean, propName); // ignore unknown properties if (metaProp != null && !metaProp.style().isDerived()) { var declaredType = SerOptional.extractType(metaProp, beanType); var value = parseProperty(entry.getValue(), declaredType, metaProp, beanType); deser.setValue(builder, metaProp, SerOptional.wrapValue(metaProp, beanType, value)); } } propName = ""; return deser.build(beanType, builder); } catch (Exception ex) { throw new IllegalArgumentException( "Error parsing bean: " + beanType.getName() + "::" + propName + ", " + ex.getMessage(), ex); } } // parse an object defined by a meta-property, event passed in private Object parseProperty( Object input, Class declaredType, MetaProperty metaProp, Class beanType) { // parse based on type if (Bean.class.isAssignableFrom(declaredType)) { return parseObjectAsBean(input, declaredType); } else if (input instanceof List || input instanceof Map) { var childIterable = settings.getIteratorFactory().createIterable(metaProp, beanType, true); return childIterable != null ? parseIterable(input, childIterable) : parseObjectAsCollection(input, declaredType); } else { return parseSimple(input, declaredType); } } // parse an object within a collection private Object parseObject( Object input, Class declaredType, SerIterable parentIterableOrNull) { if (Bean.class.isAssignableFrom(declaredType)) { return parseObjectAsBean(input, declaredType); } else if (input instanceof List || input instanceof Map) { var childIterable = parentIterableOrNull != null ? settings.getIteratorFactory().createIterable(parentIterableOrNull) : null; return childIterable != null ? parseIterable(input, childIterable) : parseObjectAsCollection(input, declaredType); } else { return parseSimple(input, declaredType); } } @SuppressWarnings("unchecked") private Object parseObjectAsBean(Object input, Class declaredType) { if (input instanceof Map) { return parseBean((Map) input, declaredType); } else { return parseSimple(input, declaredType); } } private Object parseObjectAsCollection(Object input, Class declaredType) { if (input instanceof List inputList) { if (declaredType.isArray()) { return parseIterableArray(inputList, SerIteratorFactory.array(declaredType.getComponentType())); } else { return parseIterableArray(inputList, SerIteratorFactory.list(Object.class, List.of())); } } else { return parseIterableMap(input, SerIteratorFactory.map(String.class, Object.class, List.of())); } } //----------------------------------------------------------------------- private Object parseIterable(Object input, SerIterable iterable) { return switch (iterable.category()) { case COLLECTION -> parseIterableArray((List) input, iterable); case COUNTED -> parseIterableCounted((List) input, iterable); case MAP -> parseIterableMap(input, iterable); case TABLE -> parseIterableTable((List) input, iterable); case GRID -> parseIterableGrid((List) input, iterable); }; } @SuppressWarnings("unchecked") private Object parseIterableMap(Object input, SerIterable iterable) { if (input instanceof Map) { for (var entry : ((Map) input).entrySet()) { var keyStr = entry.getKey(); var key = convertText(keyStr, iterable.keyType()); var value = parseObject(entry.getValue(), iterable.valueType(), iterable); iterable.add(key, null, value, 1); } return iterable.build(); } else if (input instanceof List inputList) { for (var inputVal : inputList) { var inputData = (List) inputVal; if (inputData.size() != 3) { throw new IllegalArgumentException("Expected table iterable to have entries of size 3"); } var key = parseObject(inputData.get(0), iterable.keyType(), null); var value = parseObject(inputData.get(2), iterable.valueType(), iterable); iterable.add(key, null, value, 1); } return iterable.build(); } else { throw new IllegalArgumentException("Invalid data: Expected List or Map but found " + input); } } private Object parseIterableTable(List input, SerIterable iterable) { for (var inputVal : input) { List inputData = (List) inputVal; if (inputData.size() != 3) { throw new IllegalArgumentException("Expected table iterable to have entries of size 3"); } var key = parseObject(inputData.get(0), iterable.keyType(), null); var col = parseObject(inputData.get(1), iterable.columnType(), null); var value = parseObject(inputData.get(2), iterable.valueType(), iterable); iterable.add(key, col, value, 1); } return iterable.build(); } private Object parseIterableGrid(List input, SerIterable iterable) { if (input.size() < 2) { throw new IllegalArgumentException("Expected grid iterable to be at least size 2"); } var rows = (Integer) input.get(0); var columns = (Integer) input.get(1); iterable.dimensions(new int[] {rows, columns}); for (var inputVal : input.subList(2, input.size())) { var inputData = (List) inputVal; if (inputData.size() != 3) { throw new IllegalArgumentException("Expected grid iterable to have entries of size 3"); } var row = (Integer) inputData.get(0); var col = (Integer) inputData.get(1); var value = parseObject(inputData.get(2), iterable.valueType(), iterable); iterable.add(row, col, value, 1); } return iterable.build(); } private Object parseIterableCounted(List input, SerIterable iterable) { for (var inputVal : input) { var inputData = (List) inputVal; if (inputData.size() != 2) { throw new IllegalArgumentException("Expected counted iterable to have entries of size 2"); } var value = parseObject(inputData.get(0), iterable.valueType(), iterable); var count = (Integer) inputData.get(1); iterable.add(null, null, value, count); } return iterable.build(); } private Object parseIterableArray(List input, SerIterable iterable) { for (var inputVal : input) { var value = parseObject(inputVal, iterable.valueType(), iterable); iterable.add(null, null, value, 1); } return iterable.build(); } //------------------------------------------------------------------------- private Object parseSimple(Object input, Class type) { return switch (input) { case null -> convertNull(type); case String s -> convertText(s, type); case Boolean b -> input; case Long l -> convertLong(l, type); case Integer i -> convertInteger(i, type); case Short s -> input; case Byte b -> input; case Double d -> convertDouble(d, type); case Float f -> convertFloat(f, type); default -> throw new IllegalArgumentException("Invalid data: Expected simple type but found " + input); }; } private Object convertNull(Class type) { if (type == double.class || type == Double.class) { return Double.NaN; // leniently accept null for NaN } else if (type == float.class || type == Float.class) { return Float.NaN; // leniently accept null for NaN } else { return null; } } private Object convertText(String input, Class type) { if (type == Object.class || type.isAssignableFrom(String.class)) { return input; } return settings.getConverter().convertFromString(type, input); } private Object convertLong(Long inputLong, Class type) { if (type == Long.class || type == long.class) { return inputLong; } else { return convertInteger(inputLong.longValue(), type); } } private Object convertInteger(Integer inputInteger, Class type) { if (type == Integer.class || type == int.class) { return inputInteger; } else { return convertInteger(inputInteger.longValue(), type); } } private Object convertDouble(Double inputDouble, Class type) { if (type == Double.class || type == double.class) { return inputDouble; } else if (type == Float.class || type == float.class) { return inputDouble.floatValue(); } else { return convertInteger(inputDouble.longValue(), type); } } private Object convertFloat(Float inputFloat, Class type) { if (type == Float.class || type == float.class) { return inputFloat; } else if (type == Double.class || type == double.class) { return inputFloat.doubleValue(); } else { return convertInteger(inputFloat.longValue(), type); } } // converts the value we received to the type we desire private Object convertInteger(long value, Class type) { if (type == Long.class || type == long.class) { return Long.valueOf(value); } else if (type == Short.class || type == short.class) { if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of short: " + value); } return Short.valueOf((short) value); } else if (type == Byte.class || type == byte.class) { if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of byte: " + value); } return Byte.valueOf((byte) value); } else if (type == Double.class || type == double.class) { double dblVal = value; if (value != (long) dblVal) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of double: " + value); } return Double.valueOf(dblVal); } else if (type == Float.class || type == float.class) { float fltVal = value; if (value != (long) fltVal) { throw new IllegalArgumentException("Invalid data: Value exceeds capacity of float: " + value); } return Float.valueOf(fltVal); } else if (type == Integer.class || type == int.class) { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { throw new IllegalArgumentException("Invalid data: Expected int, but was " + value); } return Integer.valueOf((int) value); } else { if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { return Long.valueOf(value); } return Integer.valueOf((int) value); } } } ================================================ FILE: src/main/java/org/joda/beans/ser/map/JodaBeanSimpleMapWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.map; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerCategory; import org.joda.beans.ser.SerIterator; import org.joda.beans.ser.SerOptional; /** * Provides the ability for a Joda-Bean to be written to a JSON-like in memory {@code Map}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. *

* The format used here is natural, with no meta-data. * As such, it may not be possible to write some objects or read the JSON data back in. *

* Beans are output as maps where the key is the property name. * Most simple types, defined by Joda-Convert, are output as JSON strings. * Null values are generally omitted, booleans and numbers are left as is. * Maps must have a key that can be converted to a string by Joda-Convert. * The property type needs to be known when writing/reading - properties, or * list/map entries, that are defined as {@code Object} are unlikely to work well. *

* Collections are output using lists, Maps as maps, with other collection types * having a complex list-based format. */ public class JodaBeanSimpleMapWriter { /** * The settings to use. */ private final JodaBeanSer settings; /** * Creates an instance. * * @param settings the settings to use, not null */ public JodaBeanSimpleMapWriter(JodaBeanSer settings) { JodaBeanUtils.notNull(settings, "settings"); this.settings = settings; } //----------------------------------------------------------------------- /** * Writes the bean to a string. * * @param bean the bean to output, not null * @return the JSON, not null */ public Map write(Bean bean) { JodaBeanUtils.notNull(bean, "bean"); return writeBean(bean, bean.getClass()); } //----------------------------------------------------------------------- // write a bean as a JSON object private Map writeBean(Bean bean, Class declaredType) { Map result = new LinkedHashMap<>(); // property information for (MetaProperty prop : bean.metaBean().metaPropertyIterable()) { if (prop.style().isSerializable() || (prop.style().isDerived() && settings.isIncludeDerived())) { var value = SerOptional.extractValue(prop, bean); if (value != null) { Object outputValue; Class propType = SerOptional.extractType(prop, bean.getClass()); if (value instanceof Bean beanValue) { if (settings.getConverter().isConvertible(value.getClass())) { outputValue = writeSimple(propType, value); } else { outputValue = writeBean(beanValue, propType); } } else { var itemIterator = settings.getIteratorFactory().create(value, prop, bean.getClass(), true); if (itemIterator != null) { outputValue = writeElements(itemIterator); } else { outputValue = writeSimple(propType, value); } } result.put(prop.name(), outputValue); } } } return result; } //----------------------------------------------------------------------- // write a collection private Object writeElements(SerIterator itemIterator) { if (itemIterator.category() == SerCategory.MAP) { return writeMap(itemIterator); } else if (itemIterator.category() == SerCategory.COUNTED) { return writeCounted(itemIterator); } else if (itemIterator.category() == SerCategory.TABLE) { return writeTable(itemIterator); } else if (itemIterator.category() == SerCategory.GRID) { return writeGrid(itemIterator); } else { return writeArray(itemIterator); } } // write list/set/array private Object writeArray(SerIterator itemIterator) { List result = new ArrayList<>(); while (itemIterator.hasNext()) { itemIterator.next(); result.add(writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator)); } return result; } // write map private Object writeMap(SerIterator itemIterator) { if (itemIterator.size() == 0) { return new LinkedHashMap<>(); } // if key type is known and convertible use short key format, else use full bean format if (settings.getConverter().isConvertible(itemIterator.keyType())) { return writeMapSimple(itemIterator); } else { return writeMapComplex(itemIterator); } } // write map with simple keys private Object writeMapSimple(SerIterator itemIterator) { Map result = new LinkedHashMap<>(); var keyConverter = settings.getConverter().findConverterNoGenerics(itemIterator.keyType()); while (itemIterator.hasNext()) { itemIterator.next(); var key = itemIterator.key(); if (key == null) { throw new IllegalArgumentException("Unable to write map key as it cannot be null"); } var str = keyConverter.convertToString(itemIterator.key()); if (str == null) { throw new IllegalArgumentException("Unable to write map key as it cannot be a null string"); } result.put(str, writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator)); } return result; } // write map with complex keys private Object writeMapComplex(SerIterator itemIterator) { Map result = new LinkedHashMap<>(); while (itemIterator.hasNext()) { itemIterator.next(); var key = itemIterator.key(); if (key == null) { throw new IllegalArgumentException("Unable to write map key as it cannot be null"); } var str = settings.getConverter().convertToString(itemIterator.key()); if (str == null) { throw new IllegalArgumentException("Unable to write map key as it cannot be a null string"); } result.put(str, writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator)); } return result; } // write table private Object writeTable(SerIterator itemIterator) { List result = new ArrayList<>(); while (itemIterator.hasNext()) { itemIterator.next(); var outputKey = writeObject(itemIterator.keyType(), itemIterator.key(), null); var outputCol = writeObject(itemIterator.columnType(), itemIterator.column(), null); var outputValue = writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); result.add(Arrays.asList(outputKey, outputCol, outputValue)); } return result; } // write grid using sparse approach private Object writeGrid(SerIterator itemIterator) { List result = new ArrayList<>(); result.add(itemIterator.dimensionSize(0)); result.add(itemIterator.dimensionSize(1)); while (itemIterator.hasNext()) { itemIterator.next(); var outputKey = (Integer) itemIterator.key(); var outputCol = (Integer) itemIterator.column(); var outputValue = writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); result.add(Arrays.asList(outputKey, outputCol, outputValue)); } return result; } // write counted set private Object writeCounted(final SerIterator itemIterator) { List result = new ArrayList<>(); while (itemIterator.hasNext()) { itemIterator.next(); var outputValue = writeObject(itemIterator.valueType(), itemIterator.value(), itemIterator); var outputCount = itemIterator.count(); result.add(Arrays.asList(outputValue, outputCount)); } return result; } // write collection object private Object writeObject(Class declaredType, Object obj, SerIterator parentIterator) { if (obj == null) { return null; } else if (settings.getConverter().isConvertible(obj.getClass())) { return writeSimple(declaredType, obj); } else if (obj instanceof Bean bean) { return writeBean(bean, declaredType); } else if (parentIterator != null) { var childIterator = settings.getIteratorFactory().createChild(obj, parentIterator); if (childIterator != null) { return writeElements(childIterator); } else { return writeSimple(declaredType, obj); } } else { return writeSimple(declaredType, obj); } } //----------------------------------------------------------------------- // write simple type private Object writeSimple(Class declaredType, Object value) { Class realType = value.getClass(); if (realType == Integer.class || realType == Long.class || realType == Short.class || realType == Byte.class || realType == Float.class || realType == Double.class || realType == Boolean.class) { return value; } else { // write as a string try { var converted = settings.getConverter().convertToString(realType, value); if (converted == null) { throw new IllegalArgumentException("Unable to write because converter returned a null string: " + value); } return converted; } catch (RuntimeException ex) { throw new IllegalArgumentException( "Unable to convert type " + declaredType.getName() + " for real type: " + realType.getName(), ex); } } } } ================================================ FILE: src/main/java/org/joda/beans/ser/map/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Serialization of Joda-Beans to/from an in-memory Map. */ package org.joda.beans.ser.map; ================================================ FILE: src/main/java/org/joda/beans/ser/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Serialization of Joda-Beans. *

* The main class of this package is {@link org.joda.beans.ser.JodaBeanSer JodaBeanSer}. * Configure, or use a constant, to obtain access to serialization. * From there, use one of the specific methods for JSON, XML or binary. */ package org.joda.beans.ser; ================================================ FILE: src/main/java/org/joda/beans/ser/xml/JodaBeanXml.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import javax.xml.namespace.QName; /** * Constants used in XML. */ final class JodaBeanXml { /** * XML bean tag. */ public static final String BEAN = "bean"; /** * XML bean QName. */ public static final QName BEAN_QNAME = new QName(null, BEAN); /** * XML item tag. */ public static final String ITEM = "item"; /** * XML item QName. */ public static final QName ITEM_QNAME = new QName(null, ITEM); /** * XML entry tag. */ public static final String ENTRY = "entry"; /** * XML entry QName. */ public static final QName ENTRY_QNAME = new QName(null, ENTRY); /** * XML type attribute. */ public static final String TYPE = "type"; /** * XML type QName. */ public static final QName TYPE_QNAME = new QName(null, TYPE); /** * XML key attribute. */ public static final String KEY = "key"; /** * XML key QName. */ public static final QName KEY_QNAME = new QName(null, KEY); /** * XML rows attribute. */ public static final String ROWS = "rows"; /** * XML rows QName. */ public static final QName ROWS_QNAME = new QName(null, ROWS); /** * XML cols attribute. */ public static final String COLS = "cols"; /** * XML cols QName. */ public static final QName COLS_QNAME = new QName(null, COLS); /** * XML row attribute. */ public static final String ROW = "row"; /** * XML row QName. */ public static final QName ROW_QNAME = new QName(null, ROW); /** * XML col attribute. */ public static final String COL = "col"; /** * XML col QName. */ public static final QName COL_QNAME = new QName(null, COL); /** * XML count attribute. */ public static final String COUNT = "count"; /** * XML count QName. */ public static final QName COUNT_QNAME = new QName(null, COUNT); /** * XML meta-type attribute. */ public static final String METATYPE = "metatype"; /** * XML meta-type QName. */ public static final QName METATYPE_QNAME = new QName(null, METATYPE); /** * XML null attribute. */ public static final String NULL = "null"; /** * XML null QName. */ public static final QName NULL_QNAME = new QName(null, NULL); /** * Restricted constructor. */ private JodaBeanXml() { } } ================================================ FILE: src/main/java/org/joda/beans/ser/xml/JodaBeanXmlReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import static org.joda.beans.ser.xml.JodaBeanXml.BEAN_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.COLS_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.COL_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.COUNT_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.ENTRY_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.ITEM_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.KEY_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.METATYPE_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.NULL_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.ROWS_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.ROW_QNAME; import static org.joda.beans.ser.xml.JodaBeanXml.TYPE; import static org.joda.beans.ser.xml.JodaBeanXml.TYPE_QNAME; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerCategory; import org.joda.beans.ser.SerIterable; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; /** * Provides the ability for a Joda-Bean to read from XML. *

* The XML format is defined by {@link JodaBeanXmlWriter}. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. */ public class JodaBeanXmlReader { // if you get a message like // "Message: JAXP00010001: The parser has encountered more than "64000" entity // expansions in this document; this is the limit imposed by the JDK." // then you need to update your JDK to 8u20 or later, see JDK-8028111 private static final XMLInputFactory XML_FACTORY; static { var factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_COALESCING, true); factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); XML_FACTORY = factory; } /** * Settings. */ private final JodaBeanSer settings; /** * The reader. */ private XMLEventReader reader; /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map> knownTypes = new HashMap<>(); /** * Creates an instance. * * @param settings the settings, not null */ public JodaBeanXmlReader(final JodaBeanSer settings) { this.settings = settings; } //----------------------------------------------------------------------- /** * Reads and parses to a bean. * * @param input the input string, not null * @return the bean, not null */ public Bean read(final String input) { return read(input, Bean.class); } /** * Reads and parses to a bean. * * @param the root type * @param input the input string, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(final String input, Class rootType) { return read(new StringReader(input), rootType); } /** * Reads and parses to a bean. * * @param input the input reader, not null * @return the bean, not null */ public Bean read(final InputStream input) { return read(input, Bean.class); } /** * Reads and parses to a bean. * * @param the root type * @param input the input stream, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(final InputStream input, Class rootType) { try { try { reader = XML_FACTORY.createXMLEventReader(input); return read(rootType); } finally { if (reader != null) { reader.close(); } } } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } /** * Reads and parses to a bean. * * @param input the input reader, not null * @return the bean, not null */ public Bean read(final Reader input) { return read(input, Bean.class); } /** * Reads and parses to a bean. * * @param the root type * @param input the input reader, not null * @param rootType the root type, not null * @return the bean, not null */ public T read(final Reader input, Class rootType) { try { try { reader = XML_FACTORY.createXMLEventReader(input); return read(rootType); } finally { if (reader != null) { reader.close(); } } } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new RuntimeException(ex); } } //----------------------------------------------------------------------- /** * Parses the root bean. * * @param rootType the root type, not null * @return the bean, not null * @throws Exception if an error occurs */ private T read(final Class rootType) throws Exception { var start = advanceToStartElement(); if (!start.getName().equals(BEAN_QNAME)) { throw new IllegalArgumentException("Expected root element 'bean' but found '" + start.getName() + "'"); } var attr = start.getAttributeByName(TYPE_QNAME); if (attr == null && rootType == Bean.class) { throw new IllegalArgumentException("Root element attribute must specify '" + TYPE + "'"); } Class effectiveType = rootType; if (attr != null) { var typeStr = attr.getValue(); effectiveType = SerTypeMapper.decodeType(typeStr, settings, null, knownTypes); if (!rootType.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Specified root type is incompatible with XML root type: " + rootType.getName() + " and " + effectiveType.getName()); } } if (!Bean.class.isAssignableFrom(effectiveType)) { throw new IllegalArgumentException("Root type is not a Joda-Bean: " + effectiveType.getName()); } basePackage = effectiveType.getPackage().getName() + "."; var parsed = parseBean(effectiveType); return rootType.cast(parsed); } /** * Parses a logical bean in the input XML. *

* Return type allows for a non-bean to be returned. * * @param beanType the bean type, not null * @return the bean, not null */ @SuppressWarnings("null") private Object parseBean(final Class beanType) { var propName = ""; try { XMLEvent event = null; // handle case where whole bean is Joda-Convert string if (settings.getConverter().isConvertible(beanType)) { var buf = new StringBuilder(); while (reader.hasNext()) { event = nextEvent(">btxt "); if (event.isCharacters()) { buf.append(event.asCharacters().getData()); } else if (event.isEndElement()) { return settings.getConverter().convertFromString(beanType, buf.toString()); } else if (event.isStartElement()) { break; // not serialized via Joda-Convert } else if (event.isEndDocument()) { throw new IllegalArgumentException("Unexpected end of document"); } } } else { event = nextEvent(">bean "); } // handle structured bean var deser = settings.getDeserializers().findDeserializer(beanType); var metaBean = deser.findMetaBean(beanType); BeanBuilder builder = deser.createBuilder(beanType, metaBean); // handle beans with structure while (!event.isEndElement()) { if (event.isStartElement()) { var start = event.asStartElement(); propName = start.getName().getLocalPart(); MetaProperty metaProp = deser.findMetaProperty(beanType, metaBean, propName); if (metaProp == null || metaProp.style().isDerived()) { var depth = 0; event = nextEvent(" skip "); while (!event.isEndElement() || depth > 0) { if (event.isStartElement()) { depth++; } else if (event.isEndElement()) { depth--; } event = nextEvent(" skip "); } // skip elements } else { Class childType = parseTypeAttribute(start, SerOptional.extractType(metaProp, beanType)); Object value; if (Bean.class.isAssignableFrom(childType)) { value = parseBean(childType); } else { var iterable = settings.getIteratorFactory().createIterable(metaProp, beanType); if (iterable != null) { value = parseIterable(start, iterable); } else { // metatype var metaTypeAttr = start.getAttributeByName(METATYPE_QNAME); if (metaTypeAttr != null) { iterable = settings.getIteratorFactory().createIterable(metaTypeAttr.getValue(), settings, knownTypes); if (iterable == null) { throw new IllegalArgumentException("Invalid metaType"); } value = parseIterable(start, iterable); } else { var text = advanceAndParseText(); value = settings.getConverter().convertFromString(childType, text); } } } deser.setValue(builder, metaProp, SerOptional.wrapValue(metaProp, beanType, value)); } propName = ""; } event = nextEvent(".bean "); } return deser.build(beanType, builder); } catch (Exception ex) { throw new RuntimeException("Error parsing bean: " + beanType.getName() + "::" + propName + ", " + ex.getMessage(), ex); } } /** * Parses to a collection wrapper. * * @param iterable the iterable builder, not null * @return the iterable, not null */ private Object parseIterable(final StartElement iterableEvent, final SerIterable iterable) throws Exception { var rowsAttr = iterableEvent.getAttributeByName(ROWS_QNAME); var columnsAttr = iterableEvent.getAttributeByName(COLS_QNAME); if (rowsAttr != null && columnsAttr != null) { iterable.dimensions(new int[] {Integer.parseInt(rowsAttr.getValue()), Integer.parseInt(columnsAttr.getValue())}); } var event = nextEvent(">iter "); while (!event.isEndElement()) { if (event.isStartElement()) { var start = event.asStartElement(); var expectedType = iterable.category() == SerCategory.MAP ? ENTRY_QNAME : ITEM_QNAME; if (!start.getName().equals(expectedType)) { throw new IllegalArgumentException("Expected '" + expectedType.getLocalPart() + "' but found '" + start.getName() + "'"); } var count = 1; Object key = null; Object column = null; Object value = null; if (iterable.category() == SerCategory.COUNTED) { var countAttr = start.getAttributeByName(COUNT_QNAME); if (countAttr != null) { count = Integer.parseInt(countAttr.getValue()); } value = parseValue(iterable, start); } else if (iterable.category() == SerCategory.TABLE || iterable.category() == SerCategory.GRID) { var rowAttr = start.getAttributeByName(ROW_QNAME); var colAttr = start.getAttributeByName(COL_QNAME); if (rowAttr == null || colAttr == null) { throw new IllegalArgumentException("Unable to read table as row/col attribute missing"); } var rowStr = rowAttr.getValue(); if (iterable.keyType() != null) { key = settings.getConverter().convertFromString(iterable.keyType(), rowStr); } else { key = rowStr; } var colStr = colAttr.getValue(); if (iterable.columnType() != null) { column = settings.getConverter().convertFromString(iterable.columnType(), colStr); } else { column = colStr; } value = parseValue(iterable, start); } else if (iterable.category() == SerCategory.MAP) { var keyAttr = start.getAttributeByName(KEY_QNAME); if (keyAttr != null) { // item is value with a key attribute var keyStr = keyAttr.getValue(); if (iterable.keyType() != null) { key = settings.getConverter().convertFromString(iterable.keyType(), keyStr); } else { key = keyStr; } value = parseValue(iterable, start); } else { // two items nested in this entry event = nextEvent(">>map "); var loop = 0; while (!event.isEndElement()) { if (event.isStartElement()) { start = event.asStartElement(); if (!start.getName().equals(ITEM_QNAME)) { throw new IllegalArgumentException("Expected 'item' but found '" + start.getName() + "'"); } if (key == null) { key = parseKey(iterable, start); } else { value = parseValue(iterable, start); } loop++; } event = nextEvent("..map "); } if (loop != 2) { throw new IllegalArgumentException("Expected 2 'item's but found " + loop); } } } else { // COLLECTION value = parseValue(iterable, start); } iterable.add(key, column, value, count); } event = nextEvent(".iter "); } return iterable.build(); } private Object parseKey(final SerIterable iterable, StartElement start) throws Exception { // type Class childType = parseTypeAttribute(start, iterable.keyType()); if (Bean.class.isAssignableFrom(childType) || settings.getConverter().isConvertible(childType)) { return parseBean(childType); } else if (childType.isAssignableFrom(String.class)) { return parseBean(String.class); } else { throw new IllegalArgumentException("Unable to read map as parsed key type is neither a bean nor a simple type: " + childType.getName()); } } private Object parseValue(final SerIterable iterable, StartElement start) throws Exception { // null Object value; var nullAttr = start.getAttributeByName(NULL_QNAME); if (nullAttr != null) { if (!nullAttr.getValue().equals("true")) { throw new IllegalArgumentException("Unexpected value for null attribute"); } advanceAndParseText(); // move to end tag and ignore any text value = null; } else { // type Class childType = parseTypeAttribute(start, iterable.valueType()); if (Bean.class.isAssignableFrom(childType)) { value = parseBean(childType); } else { // try deep generic parameters var childIterable = settings.getIteratorFactory().createIterable(iterable); if (childIterable != null) { value = parseIterable(start, childIterable); } else { // metatype var metaTypeAttr = start.getAttributeByName(METATYPE_QNAME); if (metaTypeAttr != null) { childIterable = settings.getIteratorFactory().createIterable(metaTypeAttr.getValue(), settings, knownTypes); if (childIterable == null) { throw new IllegalArgumentException("Invalid metaType"); } value = parseIterable(start, childIterable); } else { var text = advanceAndParseText(); value = settings.getConverter().convertFromString(childType, text); } } } } return value; } //----------------------------------------------------------------------- private Class parseTypeAttribute(StartElement start, Class defaultType) throws ClassNotFoundException { var typeAttr = start.getAttributeByName(TYPE_QNAME); if (typeAttr == null) { return (defaultType == Object.class ? String.class : defaultType); } var typeStr = typeAttr.getValue(); return settings.getDeserializers().decodeType(typeStr, settings, basePackage, knownTypes, defaultType); } // reader can be anywhere, but normally at StartDocument private StartElement advanceToStartElement() throws Exception { while (reader.hasNext()) { var event = nextEvent("advnc "); if (event.isStartElement()) { return event.asStartElement(); } } throw new IllegalArgumentException("Unexpected end of document"); } // reader must be at StartElement private String advanceAndParseText() throws Exception { var buf = new StringBuilder(); while (reader.hasNext()) { var event = nextEvent("text "); if (event.isCharacters()) { buf.append(event.asCharacters().getData()); } else if (event.isEndElement()) { return buf.toString(); } else if (event.isStartElement()) { throw new IllegalArgumentException("Unexpected start tag"); } } throw new IllegalArgumentException("Unexpected end of document"); } // provide for debugging private XMLEvent nextEvent(String location) throws Exception { var event = reader.nextEvent(); // System.out.println(location + event.toString().replace('\n', ' ') + " " + event.getClass().getSimpleName()); return event; } } ================================================ FILE: src/main/java/org/joda/beans/ser/xml/JodaBeanXmlWriter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import static org.joda.beans.ser.xml.JodaBeanXml.BEAN; import static org.joda.beans.ser.xml.JodaBeanXml.COL; import static org.joda.beans.ser.xml.JodaBeanXml.COLS; import static org.joda.beans.ser.xml.JodaBeanXml.COUNT; import static org.joda.beans.ser.xml.JodaBeanXml.ENTRY; import static org.joda.beans.ser.xml.JodaBeanXml.ITEM; import static org.joda.beans.ser.xml.JodaBeanXml.KEY; import static org.joda.beans.ser.xml.JodaBeanXml.METATYPE; import static org.joda.beans.ser.xml.JodaBeanXml.NULL; import static org.joda.beans.ser.xml.JodaBeanXml.ROW; import static org.joda.beans.ser.xml.JodaBeanXml.ROWS; import static org.joda.beans.ser.xml.JodaBeanXml.TYPE; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Objects; import org.joda.beans.Bean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerCategory; import org.joda.beans.ser.SerIterator; import org.joda.beans.ser.SerOptional; import org.joda.beans.ser.SerTypeMapper; import org.joda.convert.StringConverter; /** * Provides the ability for a Joda-Bean to be written to XML. *

* This class contains mutable state and cannot be used from multiple threads. * A new instance must be created for each message. *

* The XML consists of a root level 'bean' element with a 'type' attribute. * At each subsequent level, a bean is output using the property name. * Where necessary, the 'type' attribute is used to clarify a type. *

* Simple types, defined by Joda-Convert, are output as strings. * Beans are output recursively within the parent property element. * Collections are output using 'item' elements within the property element. * The 'item' elements will use 'key' for map keys, 'count' for multiset counts * and 'null=true' for null entries. Note that map keys must be simple types. *

* If a collection contains a collection then more information is written. * A 'metatype' attribute is added to define the high level type, such as List. * At this level, the data read back may not be identical to that written. *

* Type names are shortened by the package of the root type if possible. * Certain basic types are also handled, such as String, Integer, File and URI. */ public class JodaBeanXmlWriter { /** * The settings to use. */ private final JodaBeanSer settings; /** * The string builder, may be null. */ private final StringBuilder builder; /** * The location to output to. */ private Appendable output; /** * The root bean. */ private Bean rootBean; /** * The base package including the trailing dot. */ private String basePackage; /** * The known types. */ private final Map, String> knownTypes = new HashMap<>(); /** * Creates an instance. * * @param settings the settings to use, not null */ public JodaBeanXmlWriter(JodaBeanSer settings) { this.settings = settings; this.builder = null; } /** * Creates an instance. * * @param settings the settings to use, not null * @param builder the builder to output to, not null */ public JodaBeanXmlWriter(JodaBeanSer settings, StringBuilder builder) { this.settings = settings; this.builder = builder; } //----------------------------------------------------------------------- /** * Writes the bean to a string. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @return the XML, not null */ public String write(Bean bean) { return write(bean, true); } /** * Writes the bean to a string. * * @param bean the bean to output, not null * @param rootType true to output the root type * @return the XML, not null */ public String write(Bean bean, boolean rootType) { var builder = this.builder != null ? this.builder : new StringBuilder(1024); try { write(bean, rootType, builder); } catch (IOException ex) { throw new IllegalStateException(ex); } return builder.toString(); } /** * Writes the bean to the {@code Appendable}. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @param output the output appendable, not null * @throws IOException if an error occurs */ public void write(Bean bean, Appendable output) throws IOException { write(bean, true, output); } /** * Writes the bean to the {@code Appendable}. * * @param bean the bean to output, not null * @param rootType true to output the root type * @param output the output appendable, not null * @throws IOException if an error occurs */ public void write(Bean bean, boolean rootType, Appendable output) throws IOException { this.output = output; this.rootBean = Objects.requireNonNull(bean, "bean must not be null"); this.basePackage = (rootType ? bean.getClass().getPackage().getName() + "." : null); var type = rootBean.getClass().getName(); writeHeader(); output.append('<').append(BEAN); if (rootType) { appendAttribute(output, TYPE, type); } output.append('>').append(settings.getNewLine()); writeBean(rootBean, settings.getIndent()); output.append('<').append('/').append(BEAN).append('>').append(settings.getNewLine()); } private void writeHeader() throws IOException { output.append("").append(settings.getNewLine()); } //----------------------------------------------------------------------- private boolean willWriteBean(Bean bean) { for (MetaProperty prop : bean.metaBean().metaPropertyIterable()) { if (prop.style().isSerializable() || (prop.style().isDerived() && settings.isIncludeDerived())) { return true; } } return false; } private void writeBean(Bean bean, String currentIndent) throws IOException { for (MetaProperty prop : bean.metaBean().metaPropertyIterable()) { if (prop.style().isSerializable() || (prop.style().isDerived() && settings.isIncludeDerived())) { var value = SerOptional.extractValue(prop, bean); if (value != null) { var propName = prop.name(); Class propType = SerOptional.extractType(prop, bean.getClass()); if (value instanceof Bean beanValue) { if (settings.getConverter().isConvertible(value.getClass())) { writeSimple(currentIndent, propName, new StringBuilder(), propType, value); } else { writeBean(currentIndent, propName, new StringBuilder(), propType, beanValue); } } else { var itemIterator = settings.getIteratorFactory().create(value, prop, bean.getClass()); if (itemIterator != null) { writeElements(currentIndent, propName, new StringBuilder(), itemIterator); } else { writeSimple(currentIndent, propName, new StringBuilder(), propType, value); } } } } } } //----------------------------------------------------------------------- private void writeBean(String currentIndent, String tagName, StringBuilder attrs, Class propType, Bean value) throws IOException { if (value == null) { throw new IllegalArgumentException("Bean cannot be null"); } output.append(currentIndent).append('<').append(tagName).append(attrs); if (value.getClass() != propType) { var typeStr = SerTypeMapper.encodeType(value.getClass(), settings, basePackage, knownTypes); appendAttribute(output, TYPE, typeStr); } if (willWriteBean(value)) { output.append('>').append(settings.getNewLine()); writeBean(value, currentIndent + settings.getIndent()); output.append(currentIndent).append('<').append('/').append(tagName).append('>').append(settings.getNewLine()); } else { output.append('/').append('>').append(settings.getNewLine()); } } //----------------------------------------------------------------------- private void writeElements(String currentIndent, String tagName, StringBuilder attrs, SerIterator itemIterator) throws IOException { if (itemIterator.metaTypeRequired()) { appendAttribute(attrs, METATYPE, itemIterator.metaTypeName()); } if (itemIterator.category() == SerCategory.GRID) { appendAttribute(attrs, ROWS, Integer.toString(itemIterator.dimensionSize(0))); appendAttribute(attrs, COLS, Integer.toString(itemIterator.dimensionSize(1))); } if (itemIterator.size() == 0) { output.append(currentIndent).append('<').append(tagName).append(attrs).append('/').append('>').append(settings.getNewLine()); } else { output.append(currentIndent).append('<').append(tagName).append(attrs).append('>').append(settings.getNewLine()); writeElements(currentIndent + settings.getIndent(), itemIterator); output.append(currentIndent).append('<').append('/').append(tagName).append('>').append(settings.getNewLine()); } } private void writeElements(String currentIndent, SerIterator itemIterator) throws IOException { // find converter once for performance, and before checking if key is bean StringConverter keyConverter = null; StringConverter rowConverter = null; StringConverter columnConverter = null; var keyBean = false; if (itemIterator.category() == SerCategory.TABLE || itemIterator.category() == SerCategory.GRID) { try { rowConverter = settings.getConverter().findConverterNoGenerics(itemIterator.keyType()); } catch (RuntimeException ex) { throw new IllegalArgumentException("Unable to write table/grid as declared key type is not a simple type: " + itemIterator.keyType().getName(), ex); } try { columnConverter = settings.getConverter().findConverterNoGenerics(itemIterator.columnType()); } catch (RuntimeException ex) { throw new IllegalArgumentException("Unable to write table/grid as declared column type is not a simple type: " + itemIterator.columnType().getName(), ex); } } else if (itemIterator.category() == SerCategory.MAP) { // if key type is known and convertible use short key format, else use full bean format if (settings.getConverter().isConvertible(itemIterator.keyType())) { keyConverter = settings.getConverter().findConverterNoGenerics(itemIterator.keyType()); } else { keyBean = true; } } // output each item while (itemIterator.hasNext()) { itemIterator.next(); var attr = new StringBuilder(32); if (keyConverter != null) { var keyStr = convertToString(keyConverter, itemIterator.key(), "map key"); appendAttribute(attr, KEY, keyStr); } if (rowConverter != null) { var rowStr = convertToString(rowConverter, itemIterator.key(), "table row"); appendAttribute(attr, ROW, rowStr); var colStr = convertToString(columnConverter, itemIterator.column(), "table column"); appendAttribute(attr, COL, colStr); } if (itemIterator.count() != 1) { appendAttribute(attr, COUNT, Integer.toString(itemIterator.count())); } if (keyBean) { var key = itemIterator.key(); output.append(currentIndent).append('<').append(ENTRY).append(attr).append('>').append(settings.getNewLine()); writeKeyElement(currentIndent + settings.getIndent(), key, itemIterator); writeValueElement(currentIndent + settings.getIndent(), ITEM, new StringBuilder(), itemIterator); output.append(currentIndent).append('<').append('/').append(ENTRY).append('>').append(settings.getNewLine()); } else { var tagName = itemIterator.category() == SerCategory.MAP ? ENTRY : ITEM; writeValueElement(currentIndent, tagName, attr, itemIterator); } } } private String convertToString(StringConverter converter, Object obj, String description) { if (obj == null) { throw new IllegalArgumentException("Unable to write " + description + " as it cannot be null"); } var str = encodeAttribute(converter.convertToString(obj)); if (str == null) { throw new IllegalArgumentException("Unable to write " + description + " as it cannot be a null string: " + obj); } return str; } private void writeKeyElement(String currentIndent, Object key, SerIterator itemIterator) throws IOException { if (key == null) { throw new IllegalArgumentException("Unable to write map key as it cannot be null"); } // if key type is known and convertible use short key format if (settings.getConverter().isConvertible(itemIterator.keyType())) { writeSimple(currentIndent, ITEM, new StringBuilder(), Object.class, key); } else if (key instanceof Bean bean) { writeBean(currentIndent, ITEM, new StringBuilder(), itemIterator.keyType(), bean); } else { // this case covers where the key type is not known, such as an Object meta-property try { writeSimple(currentIndent, ITEM, new StringBuilder(), Object.class, key); } catch (RuntimeException ex) { throw new IllegalArgumentException("Unable to write map as declared key type is neither a bean nor a simple type: " + itemIterator.keyType().getName(), ex); } } } private void writeValueElement(String currentIndent, String tagName, StringBuilder attrs, SerIterator itemIterator) throws IOException { var value = itemIterator.value(); Class valueType = itemIterator.valueType(); if (value == null) { appendAttribute(attrs, NULL, "true"); output.append(currentIndent).append('<').append(tagName).append(attrs).append("/>").append(settings.getNewLine()); } else if (value instanceof Bean bean) { if (settings.getConverter().isConvertible(value.getClass())) { writeSimple(currentIndent, tagName, attrs, valueType, value); } else { writeBean(currentIndent, tagName, attrs, valueType, bean); } } else { var childIterator = settings.getIteratorFactory().createChild(value, itemIterator); if (childIterator != null) { writeElements(currentIndent, tagName, attrs, childIterator); } else { writeSimple(currentIndent, tagName, attrs, valueType, value); } } } //----------------------------------------------------------------------- private void writeSimple(String currentIndent, String tagName, StringBuilder attrs, Class declaredType, Object value) throws IOException { Class effectiveType; if (declaredType == Object.class) { Class realType = value.getClass(); if (realType != String.class) { effectiveType = settings.getConverter().findTypedConverter(realType).getEffectiveType(); var typeStr = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); appendAttribute(attrs, TYPE, typeStr); } else { effectiveType = realType; } } else if (!settings.getConverter().isConvertible(declaredType)) { effectiveType = settings.getConverter().findTypedConverter(value.getClass()).getEffectiveType(); var typeStr = SerTypeMapper.encodeType(effectiveType, settings, basePackage, knownTypes); appendAttribute(attrs, TYPE, typeStr); } else { effectiveType = declaredType; } try { var converted = settings.getConverter().convertToString(effectiveType, value); if (converted == null) { throw new IllegalArgumentException("Unable to write because converter returned a null string: " + value); } output.append(currentIndent).append('<').append(tagName).append(attrs).append('>'); appendEncoded(converted); output.append('<').append('/').append(tagName).append('>').append(settings.getNewLine()); } catch (RuntimeException ex) { throw new IllegalArgumentException("Unable to convert type " + effectiveType.getName() + " declared as " + declaredType.getName(), ex); } } private void appendEncoded(String text) throws IOException { for (var i = 0; i < text.length(); i++) { var ch = text.charAt(i); switch (ch) { case '&': output.append("&"); break; case '<': output.append("<"); break; case '>': output.append(">"); break; case '\t': case '\n': case '\r': output.append(ch); break; default: if (ch < 32) { throw new IllegalArgumentException("Invalid character for XML: " + ((int) ch)); } output.append(ch); break; } } } //----------------------------------------------------------------------- private void appendAttribute(Appendable buf, String attrName, String encodedValue) throws IOException { buf.append(' ').append(attrName).append('=').append('\"').append(encodedValue).append('\"'); } private String encodeAttribute(String text) { if (text == null) { return null; } return appendEncodedAttribute(new StringBuilder(text.length() + 16), text).toString(); } private StringBuilder appendEncodedAttribute(StringBuilder builder, String text) { for (var i = 0; i < text.length(); i++) { var ch = text.charAt(i); switch (ch) { case '&': builder.append("&"); break; case '<': builder.append("<"); break; case '>': builder.append(">"); break; case '"': builder.append("""); break; case '\'': builder.append("'"); break; case '\t': builder.append(" "); break; case '\n': builder.append("�A;"); break; case '\r': builder.append("�D;"); break; default: if (ch < 32) { throw new IllegalArgumentException("Invalid character for XML: " + ((int) ch)); } builder.append(ch); break; } } return builder; } } ================================================ FILE: src/main/java/org/joda/beans/ser/xml/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Serialization of Joda-Beans using XML. */ package org.joda.beans.ser.xml; ================================================ FILE: src/main/java/org/joda/beans/test/BeanAssert.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.test; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; /** * Assertion class to compare beans. *

* This class fulfils a similar role to other assertion libraries in testing code. * It should generally be statically imported. */ public final class BeanAssert { /** * Restricted constructor. */ private BeanAssert() { } //----------------------------------------------------------------------- /** * Asserts that two beans are equal, providing a better error message. * * @param expected the expected value, not null * @param actual the actual value, not null */ public static void assertBeanEquals(Bean expected, Bean actual) { assertBeanEquals(null, expected, actual, 0d); } /** * Asserts that two beans are equal, providing a better error message. *

* Note that specifying a tolerance can mean that two beans compare as not * equal using {@link Object#equals(Object)} but equal using this method, * because the standard equals method has no tolerance. * * @param expected the expected value, not null * @param actual the actual value, not null * @param tolerance the tolerance to use for {@code double} and {@code float} */ public static void assertBeanEquals(Bean expected, Bean actual, double tolerance) { assertBeanEquals(null, expected, actual, tolerance); } /** * Asserts that two beans are equal, providing a better error message. * * @param baseMsg the message to use in any error, null uses default message * @param expected the expected value, not null * @param actual the actual value, not null */ public static void assertBeanEquals(String baseMsg, Bean expected, Bean actual) { assertBeanEquals(baseMsg, expected, actual, 0d); } /** * Asserts that two beans are equal, providing a better error message. *

* Note that specifying a tolerance can mean that two beans compare as not * equal using {@link Object#equals(Object)} but equal using this method, * because the standard equals method has no tolerance. * * @param baseMsg the message to use in any error, null uses default message * @param expected the expected value, not null * @param actual the actual value, not null * @param tolerance the tolerance to use for {@code double} and {@code float} */ public static void assertBeanEquals(String baseMsg, Bean expected, Bean actual, double tolerance) { if (expected == null) { throw new AssertionError(baseMsg + ": Expected bean must not be null"); } if (actual == null) { throw new AssertionError(baseMsg + ": Actual bean must not be null"); } if (!expected.equals(actual)) { var comparisonMsg = buildMessage(baseMsg, 10, expected, actual, tolerance); if (comparisonMsg.isEmpty()) { return; // no errors, just double/float within tolerance } throw new BeanComparisonError(comparisonMsg, expected, actual); } } //----------------------------------------------------------------------- /** * Asserts that two beans are equal, providing a better error message. * * @param expected the expected value, not null * @param actual the actual value, not null */ public static void assertBeanEqualsFullDetail(Bean expected, Bean actual) { assertBeanEqualsFullDetail(null, expected, actual, 0d); } /** * Asserts that two beans are equal, providing a better error message. *

* Note that specifying a tolerance can mean that two beans compare as not * equal using {@link Object#equals(Object)} but equal using this method, * because the standard equals method has no tolerance. * * @param expected the expected value, not null * @param actual the actual value, not null * @param tolerance the tolerance to use for {@code double} and {@code float} */ public static void assertBeanEqualsFullDetail(Bean expected, Bean actual, double tolerance) { assertBeanEqualsFullDetail(null, expected, actual, tolerance); } /** * Asserts that two beans are equal, providing a better error message, with * an unlimited number of errors reported. * * @param baseMsg the message to use in any error, null uses default message * @param expected the expected value, not null * @param actual the actual value, not null */ public static void assertBeanEqualsFullDetail(String baseMsg, Bean expected, Bean actual) { assertBeanEqualsFullDetail(baseMsg, expected, actual, 0d); } /** * Asserts that two beans are equal, providing a better error message, with * an unlimited number of errors reported. *

* Note that specifying a tolerance can mean that two beans compare as not * equal using {@link Object#equals(Object)} but equal using this method, * because the standard equals method has no tolerance. * * @param baseMsg the message to use in any error, null uses default message * @param expected the expected value, not null * @param actual the actual value, not null * @param tolerance the tolerance to use for {@code double} and {@code float} */ public static void assertBeanEqualsFullDetail(String baseMsg, Bean expected, Bean actual, double tolerance) { if (expected == null) { throw new AssertionError(baseMsg + ": Expected bean must not be null"); } if (actual == null) { throw new AssertionError(baseMsg + ": Actual bean must not be null"); } if (!expected.equals(actual)) { var comparisonMsg = buildMessage(baseMsg, Integer.MAX_VALUE, expected, actual, tolerance); if (comparisonMsg.isEmpty()) { return; // no errors, just double/float within tolerance } throw new BeanComparisonError(comparisonMsg, expected, actual); } } //----------------------------------------------------------------------- /** * Compares the two beans. * * @param baseMsg the message, may be null * @param maxErrors the maximum number of errors to report * @param expected the expected value, not null * @param actual the actual value, not null * @param tolerance the tolerance to use for {@code double} and {@code float} * @return the message, not null */ private static String buildMessage(String baseMsg, int maxErrors, Bean expected, Bean actual, double tolerance) { List diffs = new ArrayList<>(); buildMessage(diffs, "", expected, actual, tolerance); if (diffs.isEmpty()) { return ""; } var buf = new StringBuilder(); buf.append(baseMsg != null ? baseMsg + ": " : ""); buf.append("Bean did not equal expected. Differences:"); var size = diffs.size(); if (size > maxErrors) { diffs = diffs.subList(0, maxErrors); } for (String diff : diffs) { buf.append('\n').append(diff); } if (size > maxErrors) { buf.append("\n...and ").append(size - 10).append(" more differences"); } return buf.toString(); } private static void buildMessage(List diffs, String prefix, Object expected, Object actual, double tolerance) { if (expected == null) { if (actual == null) { return; } else { diffs.add(prefix + ": Expected null, but was " + buildSummary(actual, true)); return; } } if (actual == null) { diffs.add(prefix + ": Was null, but expected " + buildSummary(expected, true)); return; } if (expected.equals(actual)) { return; } if (expected instanceof List expectedList && actual instanceof List actualList) { if (expectedList.size() != actualList.size()) { diffs.add(prefix + ": List size differs, expected " + expectedList.size() + " but was " + actualList.size()); return; } for (var i = 0; i < expectedList.size(); i++) { buildMessage(diffs, prefix + '[' + i + "]", expectedList.get(i), actualList.get(i), tolerance); } return; } if (expected instanceof Map expectedMap && actual instanceof Map actualMap) { if (expectedMap.size() != actualMap.size()) { diffs.add(prefix + ": Map size differs, expected " + expectedMap.size() + " but was " + actualMap.size()); return; } if (!expectedMap.keySet().equals(actualMap.keySet())) { diffs.add(prefix + ": Map keySet differs, expected " + buildSummary(expectedMap.keySet(), false) + " but was " + buildSummary(actualMap.keySet(), false)); return; } for (var key : expectedMap.keySet()) { buildMessage(diffs, prefix + '[' + key + "]", expectedMap.get(key), actualMap.get(key), tolerance); } return; } if (expected.getClass() != actual.getClass()) { diffs.add(prefix + ": Class differs, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, true)); return; } if (expected instanceof Bean) { for (MetaProperty prop : ((Bean) expected).metaBean().metaPropertyIterable()) { buildMessage(diffs, prefix + '.' + prop.name(), prop.get((Bean) expected), prop.get((Bean) actual), tolerance); } return; } if (expected instanceof Double e && tolerance != 0d) { var a = (Double) actual; if (!JodaBeanUtils.equalWithTolerance(e, a, tolerance)) { diffs.add(prefix + ": Double values differ by more than allowed tolerance, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); } return; } if (expected instanceof double[] e && tolerance != 0d) { var a = (double[]) actual; if (e.length != a.length) { diffs.add(prefix + ": Double arrays differ in length, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); } else { for (var i = 0; i < a.length; i++) { if (!JodaBeanUtils.equalWithTolerance(e[i], a[i], tolerance)) { diffs.add(prefix + ": Double arrays differ by more than allowed tolerance, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); break; } } } return; } if (expected instanceof Float e && tolerance != 0d) { var a = (Float) actual; if (!JodaBeanUtils.equalWithTolerance(e, a, tolerance)) { diffs.add(prefix + ": Float values differ by more than allowed tolerance, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); } return; } if (expected instanceof float[] e && tolerance != 0d) { var a = (float[]) actual; if (e.length != a.length) { diffs.add(prefix + ": Float arrays differ in length, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); } else { for (var i = 0; i < a.length; i++) { if (!JodaBeanUtils.equalWithTolerance(e[i], a[i], tolerance)) { diffs.add(prefix + ": Float arrays differ by more than allowed tolerance, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); break; } } } return; } if (!JodaBeanUtils.equal(expected, actual)) { diffs.add(prefix + ": Content differs, expected " + buildSummary(expected, true) + " but was " + buildSummary(actual, false)); } // equal } /** * Builds a summary of an object. * * @param obj the object to summarise, not null */ private static String buildSummary(Object obj, boolean includeType) { var type = obj.getClass().getSimpleName(); var toStr = JodaBeanUtils.toString(obj); if (toStr.length() > 60) { toStr = toStr.substring(0, 57) + "..."; } return (includeType ? type + " " : "") + "<" + toStr + ">"; } } ================================================ FILE: src/main/java/org/joda/beans/test/BeanComparisonError.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.test; import java.io.Serial; import org.joda.beans.Bean; /** * Error class used when two beans fail to compare. */ class BeanComparisonError extends AssertionError { /** Serialization version. */ @Serial private static final long serialVersionUID = 1L; /** * The expected bean. */ private final Bean expected; /** * The actual bean. */ private final Bean actual; /** * Creates a new error. * * @param message the message, may be null * @param expected the expected value, not null * @param actual the actual value, not null */ BeanComparisonError(String message, Bean expected, Bean actual) { super(message); this.expected = expected; this.actual = actual; } //------------------------------------------------------------------------- /** * Gets the expected field. * @return the expected */ public Bean getExpected() { return expected; } /** * Gets the actual field. * @return the actual */ public Bean getActual() { return actual; } } ================================================ FILE: src/main/java/org/joda/beans/test/JodaBeanTests.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.test; import java.lang.reflect.Modifier; import java.net.URI; import java.time.DayOfWeek; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; import java.time.Year; import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; /** * A utility class to assist with testing beans. *

* Test coverage statistics can be heavily skewed by getters, setters and generated code. * This class provides a solution, allowing bean test coverage to be artificially increased. * Always remember that the goal of artificially increasing coverage is so that you can * see what you really need to test, not to avoid writing tests altogether. */ public final class JodaBeanTests { /** * This constant can be used to pass to increase test coverage. * This is used by some {@link MetaBean} methods in generated classes. */ public static final String TEST_COVERAGE_PROPERTY = "!ConstantUsedForTestCoveragePurposes!"; /** * This constant can be used to pass to increase test coverage. * This is used by some {@link BeanBuilder} set methods in generated classes. */ public static final String TEST_COVERAGE_STRING = "!ConstantUsedForTestCoveragePurposes!"; //------------------------------------------------------------------------- /** * Test a mutable bean for the primary purpose of increasing test coverage. * * @param bean the bean to test */ public static void coverMutableBean(Bean bean) { assertNotNull(bean, "coverImmutableBean() called with null bean"); assertFalse(bean instanceof ImmutableBean); assertNotSame(JodaBeanUtils.clone(bean), bean); coverBean(bean); } /** * Test an immutable bean for the primary purpose of increasing test coverage. * * @param bean the bean to test */ public static void coverImmutableBean(ImmutableBean bean) { assertNotNull(bean, "coverImmutableBean() called with null bean"); assertSame(JodaBeanUtils.clone(bean), bean); coverBean(bean); } /** * Test a bean equals method for the primary purpose of increasing test coverage. *

* The two beans passed in should contain a different value for each property. * The method creates a cross-product to ensure test coverage of equals. * * @param bean1 the first bean to test * @param bean2 the second bean to test */ @SuppressWarnings("unlikely-arg-type") public static void coverBeanEquals(Bean bean1, Bean bean2) { assertNotNull(bean1, "coverBeanEquals() called with null bean"); assertNotNull(bean2, "coverBeanEquals() called with null bean"); assertFalse(bean1.equals(null)); assertFalse(bean1.equals("NonBean")); assertTrue(bean1.equals(bean1)); assertTrue(bean2.equals(bean2)); ignoreThrows(() -> assertEquals(bean1, JodaBeanUtils.cloneAlways(bean1))); ignoreThrows(() -> assertEquals(bean2, JodaBeanUtils.cloneAlways(bean2))); assertTrue(bean1.hashCode() == bean1.hashCode()); assertTrue(bean2.hashCode() == bean2.hashCode()); if (bean1.equals(bean2) || bean1.getClass() != bean2.getClass()) { return; } var metaBean = bean1.metaBean(); var buildableProps = metaBean.metaPropertyMap().values().stream() .filter(mp -> mp.style().isBuildable()) .toList(); var builtBeansSet = new HashSet(); builtBeansSet.add(bean1); builtBeansSet.add(bean2); for (var i = 0; i < buildableProps.size(); i++) { for (var j = 0; j < 2; j++) { try { var bld = metaBean.builder(); for (var k = 0; k < buildableProps.size(); k++) { MetaProperty mp = buildableProps.get(k); if (j == 0) { bld.set(mp, mp.get(k < i ? bean1 : bean2)); } else { bld.set(mp, mp.get(i <= k ? bean1 : bean2)); } } builtBeansSet.add(bld.build()); } catch (RuntimeException ex) { // ignore } } } var builtBeansList = new ArrayList<>(builtBeansSet); for (var i = 0; i < builtBeansList.size() - 1; i++) { for (var j = i + 1; j < builtBeansList.size(); j++) { builtBeansList.get(i).equals(builtBeansList.get(j)); } } } // provide test coverage to all beans private static void coverBean(Bean bean) { coverProperties(bean); coverNonProperties(bean); coverEquals(bean); } // cover parts of a bean that are property-based private static void coverProperties(Bean bean) { var metaBean = bean.metaBean(); var metaPropMap = metaBean.metaPropertyMap(); assertNotNull(metaPropMap); assertEquals(metaBean.metaPropertyCount(), metaPropMap.size()); for (var mp : metaBean.metaPropertyIterable()) { assertTrue(metaBean.metaPropertyExists(mp.name())); assertEquals(metaBean.metaProperty(mp.name()), mp); // Ensure we don't use interned value assertEquals(metaBean.metaProperty(new String(mp.name())), mp); assertEquals(metaPropMap.containsValue(mp), true); assertEquals(metaPropMap.containsKey(mp.name()), true); if (mp.style().isReadable()) { ignoreThrows(() -> mp.get(bean)); } else { assertThrows(() -> mp.get(bean), UnsupportedOperationException.class); } if (mp.style().isWritable()) { ignoreThrows(() -> mp.set(bean, "")); } else { assertThrows(() -> mp.set(bean, ""), UnsupportedOperationException.class); } if (mp.style().isBuildable()) { ignoreThrows(() -> metaBean.builder().get(mp)); ignoreThrows(() -> metaBean.builder().get(mp.name())); for (Object setValue : sampleValues(mp)) { ignoreThrows(() -> metaBean.builder().set(mp, setValue)); } for (Object setValue : sampleValues(mp)) { ignoreThrows(() -> metaBean.builder().set(mp.name(), setValue)); } } ignoreThrows(() -> { var m = metaBean.getClass().getDeclaredMethod(mp.name()); m.setAccessible(true); m.invoke(metaBean); }); ignoreThrows(() -> { var m = metaBean.getClass().getDeclaredMethod( "propertySet", Bean.class, String.class, Object.class, Boolean.TYPE); m.setAccessible(true); m.invoke(metaBean, bean, mp.name(), "", true); }); } ignoreThrows(() -> { var m = metaBean.getClass().getDeclaredMethod( "propertyGet", Bean.class, String.class, Boolean.TYPE); m.setAccessible(true); m.invoke(metaBean, bean, "Not a real property name", true); }); MetaProperty fakeMetaProp = StandaloneMetaProperty.of("fake", metaBean, String.class); ignoreThrows(() -> metaBean.builder().set(fakeMetaProp, JodaBeanTests.TEST_COVERAGE_STRING)); ignoreThrows(() -> metaBean.builder().set(JodaBeanTests.TEST_COVERAGE_PROPERTY, JodaBeanTests.TEST_COVERAGE_STRING)); ignoreThrows(() -> bean.property(JodaBeanTests.TEST_COVERAGE_PROPERTY)); } // cover parts of a bean that are not property-based private static void coverNonProperties(Bean bean) { var metaBean = bean.metaBean(); assertFalse(metaBean.metaPropertyExists("")); assertThrows(() -> metaBean.builder().get("foo_bar"), NoSuchElementException.class); assertThrows(() -> metaBean.builder().set("foo_bar", ""), NoSuchElementException.class); assertThrows(() -> metaBean.metaProperty("foo_bar"), NoSuchElementException.class); if (metaBean instanceof DirectMetaBean) { var dummy = DirectMetaProperty.ofReadWrite(metaBean, "foo_bar", metaBean.beanType(), String.class); assertThrows(() -> dummy.get(bean), NoSuchElementException.class); assertThrows(() -> dummy.set(bean, ""), NoSuchElementException.class); assertThrows(() -> dummy.setString(bean, ""), NoSuchElementException.class); assertThrows(() -> metaBean.builder().get(dummy), NoSuchElementException.class); assertThrows(() -> metaBean.builder().set(dummy, ""), NoSuchElementException.class); } var propertyNameSet = bean.propertyNames(); assertNotNull(propertyNameSet); for (String propertyName : propertyNameSet) { assertNotNull(bean.property(propertyName)); } assertThrows(() -> bean.property(""), NoSuchElementException.class); var beanClass = bean.getClass(); ignoreThrows(() -> { var m = beanClass.getDeclaredMethod("meta"); m.setAccessible(true); m.invoke(null); }); ignoreThrows(() -> { var m = beanClass.getDeclaredMethod("meta" + beanClass.getSimpleName(), Class.class); m.setAccessible(true); m.invoke(null, String.class); }); ignoreThrows(() -> { var m = beanClass.getDeclaredMethod("meta" + beanClass.getSimpleName(), Class.class, Class.class); m.setAccessible(true); m.invoke(null, String.class, String.class); }); ignoreThrows(() -> { var m = beanClass.getDeclaredMethod("meta" + beanClass.getSimpleName(), Class.class, Class.class, Class.class); m.setAccessible(true); m.invoke(null, String.class, String.class, String.class); }); ignoreThrows(() -> { var m = bean.getClass().getDeclaredMethod("builder"); m.setAccessible(true); m.invoke(null); }); ignoreThrows(() -> { var m = bean.getClass().getDeclaredMethod("toBuilder"); m.setAccessible(true); m.invoke(bean); }); assertNotNull(bean.toString()); assertNotNull(metaBean.toString()); assertNotNull(metaBean.builder().toString()); } // different combinations of values to cover equals() @SuppressWarnings("unlikely-arg-type") private static void coverEquals(Bean bean) { // create beans with different data and compare each to the input bean // this will normally trigger each of the possible branches in equals var buildableProps = bean.metaBean().metaPropertyMap().values().stream() .filter(mp -> mp.style().isBuildable()) .toList(); for (var i = 0; i < buildableProps.size(); i++) { try { var bld = bean.metaBean().builder(); for (var j = 0; j < buildableProps.size(); j++) { var mp = buildableProps.get(j); if (j < i) { bld.set(mp, mp.get(bean)); } else { var samples = sampleValues(mp); bld.set(mp, samples.get(0)); } } var built = bld.build(); coverBeanEquals(bean, built); assertEquals(built, built); assertEquals(built.hashCode(), built.hashCode()); } catch (RuntimeException ex) { // ignore } } // cover the remaining equals edge cases assertFalse(bean.equals(null)); assertFalse(bean.equals("NonBean")); assertTrue(bean.equals(bean)); ignoreThrows(() -> assertEquals(bean, JodaBeanUtils.cloneAlways(bean))); assertTrue(bean.hashCode() == bean.hashCode()); } // sample values for setters private static List sampleValues(MetaProperty mp) { var type = mp.propertyType(); // enum constants if (Enum.class.isAssignableFrom(type)) { return Arrays.asList(type.getEnumConstants()); } // lookup pre-canned samples var sample = SAMPLES.get(type); if (sample != null) { return sample; } // find any potential declared constants, using some plural rules var typeName = type.getName(); var samples = new ArrayList<>(); samples.addAll(buildSampleConstants(type, type)); ignoreThrows(() -> { // cat -> cats samples.addAll(buildSampleConstants(Class.forName(typeName + "s"), type)); }); ignoreThrows(() -> { // dish -> dishes samples.addAll(buildSampleConstants(Class.forName(typeName + "es"), type)); }); ignoreThrows(() -> { // lady -> ladies samples.addAll(buildSampleConstants(Class.forName(typeName.substring(0, typeName.length() - 1) + "ies"), type)); }); ignoreThrows(() -> { // index -> indices samples.addAll(buildSampleConstants(Class.forName(typeName.substring(0, typeName.length() - 2) + "ices"), type)); }); // none return samples; } // adds sample constants to the private static List buildSampleConstants(Class queryType, Class targetType) { var samples = new ArrayList<>(); for (var field : queryType.getFields()) { if (field.getType() == targetType && Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) && !field.isSynthetic()) { ignoreThrows(() -> samples.add(field.get(null))); } } return samples; } private static final Map, List> SAMPLES; static { var map = new HashMap, List>(); map.put(String.class, List.of("Hello", "Goodbye", " ", "")); map.put(Byte.class, List.of((byte) 0, (byte) 1)); map.put(Byte.TYPE, List.of((byte) 0, (byte) 1)); map.put(Short.class, List.of((short) 0, (short) 1)); map.put(Short.TYPE, List.of((short) 0, (short) 1)); map.put(Integer.class, List.of(0, 1)); map.put(Integer.TYPE, List.of(0, 1)); map.put(Long.class, List.of((long) 0, (long) 1)); map.put(Long.TYPE, List.of((long) 0, (long) 1)); map.put(Float.class, List.of((float) 0, (float) 1)); map.put(Float.TYPE, List.of((float) 0, (float) 1)); map.put(Double.class, List.of((double) 0, (double) 1)); map.put(Double.TYPE, List.of((double) 0, (double) 1)); map.put(Character.class, List.of(' ', 'A', 'z')); map.put(Character.TYPE, List.of(' ', 'A', 'z')); map.put(Boolean.class, List.of(Boolean.TRUE, Boolean.FALSE)); map.put(Boolean.TYPE, List.of(Boolean.TRUE, Boolean.FALSE)); map.put(LocalDate.class, List.of(LocalDate.now(ZoneOffset.UTC), LocalDate.of(2012, 6, 30))); map.put(LocalTime.class, List.of(LocalTime.now(ZoneOffset.UTC), LocalTime.of(11, 30))); map.put(LocalDateTime.class, List.of(LocalDateTime.now(ZoneOffset.UTC), LocalDateTime.of(2012, 6, 30, 11, 30))); map.put(OffsetTime.class, List.of(OffsetTime.now(ZoneOffset.UTC), OffsetTime.of(11, 30, 0, 0, ZoneOffset.ofHours(1)))); map.put(OffsetDateTime.class, List.of( OffsetDateTime.now(ZoneOffset.UTC), OffsetDateTime.of(2012, 6, 30, 11, 30, 0, 0, ZoneOffset.ofHours(1)))); map.put(ZonedDateTime.class, List.of( ZonedDateTime.now(ZoneOffset.UTC), ZonedDateTime.of(2012, 6, 30, 11, 30, 0, 0, ZoneId.systemDefault()))); map.put(Instant.class, List.of(Instant.now(), Instant.EPOCH)); map.put(Year.class, List.of(Year.now(ZoneOffset.UTC), Year.of(2012))); map.put(YearMonth.class, List.of(YearMonth.now(ZoneOffset.UTC), YearMonth.of(2012, 6))); map.put(MonthDay.class, List.of(MonthDay.now(ZoneOffset.UTC), MonthDay.of(12, 25))); map.put(Month.class, List.of(Month.JULY, Month.DECEMBER)); map.put(DayOfWeek.class, List.of(DayOfWeek.FRIDAY, DayOfWeek.SATURDAY)); map.put(URI.class, List.of(URI.create("http://www.opengamma.com"), URI.create("http://www.joda.org"))); map.put(Class.class, List.of(Throwable.class, RuntimeException.class, String.class)); map.put(Object.class, List.of("", 6)); map.put(Collection.class, List.of(new ArrayList<>())); map.put(List.class, List.of(new ArrayList<>())); map.put(Set.class, List.of(new HashSet<>())); map.put(SortedSet.class, List.of(new TreeSet<>())); try { var cls = Class.forName("com.google.common.collect.ImmutableList"); var method = cls.getDeclaredMethod("of"); map.put(cls, List.of(method.invoke(null))); } catch (Exception ex) { // ignore } try { var cls = Class.forName("com.google.common.collect.ImmutableSet"); var method = cls.getDeclaredMethod("of"); map.put(cls, List.of(method.invoke(null))); } catch (Exception ex) { // ignore } try { var cls = Class.forName("com.google.common.collect.ImmutableSortedSet"); var method = cls.getDeclaredMethod("naturalOrder"); map.put(cls, List.of(method.invoke(null))); } catch (Exception ex) { // ignore } try { var cls = Class.forName("com.google.common.collect.ImmutableMap"); var method = cls.getDeclaredMethod("of"); map.put(cls, List.of(method.invoke(null))); } catch (Exception ex) { // ignore } SAMPLES = map; } //----------------------------------------------------------------------- private static void assertNotNull(Object obj) { if (obj == null) { throw new AssertionError("Expected (a != null), but found (a == null)"); } } private static void assertNotNull(Object obj, String message) { if (obj == null) { throw new AssertionError(message); } } private static void assertSame(Object a, Object b) { if (a != b) { throw new AssertionError("Expected (a == b), but found (a != b)"); } } private static void assertNotSame(Object a, Object b) { if (a == b) { throw new AssertionError("Expected (a != b), but found (a == b)"); } } private static void assertEquals(Object actual, Object expected) { if (!Objects.equals(actual, expected)) { throw new AssertionError("Expected " + expected + ", but found " + actual); } } private static void assertEquals(int actual, int expected) { if (actual != expected) { throw new AssertionError("Expected " + expected + ", but found " + actual); } } private static void assertTrue(boolean actual) { if (!actual) { throw new AssertionError("Expected value to be true, but was false"); } } private static void assertFalse(boolean actual) { if (actual) { throw new AssertionError("Expected value to be false, but was true"); } } //----------------------------------------------------------------------- private static void assertThrows(AssertRunnable runner, Class expected) { assertNotNull(runner, "assertThrows() called with null AssertRunnable"); assertNotNull(expected, "assertThrows() called with null expected Class"); try { runner.run(); throw new AssertionError("Expected " + expected.getSimpleName() + " but code succeeded normally"); } catch (AssertionError ex) { throw ex; } catch (Throwable ex) { if (!expected.isInstance(ex)) { throw new AssertionError( "Expected " + expected.getSimpleName() + " but received " + ex.getClass().getSimpleName(), ex); } } } private static void ignoreThrows(AssertRunnable runner) { assertNotNull(runner, "ignoreThrows() called with null AssertRunnable"); try { runner.run(); } catch (Throwable ex) { // ignore } } @FunctionalInterface interface AssertRunnable { /** * Used to wrap code that is expected to throw an exception. * * @throws Throwable the expected result */ void run() throws Throwable; } } ================================================ FILE: src/main/java/org/joda/beans/test/package-info.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Utility to assist with testing and comparing Joda-Beans. *

* This provides the ability to compare two beans in a much more effective way. */ package org.joda.beans.test; ================================================ FILE: src/main/resources/org/joda/beans/gen/guava.ini ================================================ # copies requiring Guava library or Joda-Collect # ImmutableCollection is abstract, thus uses ImmutableList/ArrayList # TreeMultiset use only works with natural ordering # how to copy $value to make it immutable [immutable.builder.to.immutable] Collection = ImmutableList.copyOf($value) List = ImmutableList.copyOf($value) Set = ImmutableSet.copyOf($value) SortedSet = ImmutableSortedSet.copyOfSorted($value) Map = ImmutableMap.copyOf($value) SortedMap = ImmutableSortedMap.copyOfSorted($value) EnumSet = EnumSet.copyOf($value) NavigableSet = Sets.unmodifiableNavigableSet(Sets.newTreeSet($value)) NavigableMap = Maps.unmodifiableNavigableMap(Maps.newTreeMap($value)) BiMap = ImmutableBiMap.copyOf($value) Multimap = ImmutableMultimap.copyOf($value) ListMultimap = ImmutableListMultimap.copyOf($value) SetMultimap = ImmutableSetMultimap.copyOf($value) Multiset = ImmutableMultiset.copyOf($value) SortedMultiset = ImmutableSortedMultiset.copyOfSorted($value) Table = ImmutableTable.copyOf($value) Grid = ImmutableGrid.copyOf($value) ImmutableCollection = ImmutableList.copyOf($value) ImmutableList = ImmutableList.copyOf($value) ImmutableSet = ImmutableSet.copyOf($value) ImmutableSortedSet = ImmutableSortedSet.copyOfSorted($value) ImmutableMap = ImmutableMap.copyOf($value) ImmutableSortedMap = ImmutableSortedMap.copyOfSorted($value) ImmutableBiMap = ImmutableBiMap.copyOf($value) ImmutableMultimap = ImmutableMultimap.copyOf($value) ImmutableListMultimap = ImmutableListMultimap.copyOf($value) ImmutableSetMultimap = ImmutableSetMultimap.copyOf($value) ImmutableMultiset = ImmutableMultiset.copyOf($value) ImmutableSortedMultiset = ImmutableSortedMultiset.copyOfSorted($value) ImmutableTable = ImmutableTable.copyOf($value) ImmutableGrid = ImmutableGrid.copyOf($value) ImmutableBean = $value # how to copy $value to make it mutable [immutable.builder.to.mutable] Collection = ImmutableList.copyOf($value) List = ImmutableList.copyOf($value) Set = ImmutableSet.copyOf($value) SortedSet = ImmutableSortedSet.copyOfSorted($value) Map = ImmutableMap.copyOf($value) SortedMap = ImmutableSortedMap.copyOfSorted($value) EnumSet = new HashSet<>($value) NavigableSet = new TreeSet<>($value)) NavigableMap = new TreeMap<>($value) BiMap = ImmutableBiMap.copyOf($value) Multimap = ImmutableMultimap.copyOf($value) ListMultimap = ImmutableListMultimap.copyOf($value) SetMultimap = ImmutableSetMultimap.copyOf($value) Multiset = ImmutableMultiset.copyOf($value) SortedMultiset = ImmutableSortedMultiset.copyOfSorted($value) Table = ImmutableTable.copyOf($value) Grid = ImmutableGrid.copyOf($value) ImmutableCollection = $value ImmutableList = $value ImmutableSet = $value ImmutableSortedSet = $value ImmutableMap = $value ImmutableSortedMap = $value ImmutableBiMap = $value ImmutableMultimap = $value ImmutableListMultimap = $value ImmutableSetMultimap = $value ImmutableMultiset = $value ImmutableSortedMultiset = $value ImmutableTable = $value ImmutableGrid = $value ImmutableBean = $value # the type to use for in the builder [immutable.builder.type] EnumSet = Set<> ImmutableCollection = Collection<> ImmutableList = List<> ImmutableSet = Set<> ImmutableSortedSet = SortedSet<> ImmutableMap = Map<> ImmutableSortedMap = SortedMap<> ImmutableBiMap = BiMap<> ImmutableMultimap = Multimap<> ImmutableListMultimap = ListMultimap<> ImmutableSetMultimap = SetMultimap<> ImmutableMultiset = Multiset<> ImmutableSortedMultiset = SortedMultiset<> ImmutableTable = Table<> ImmutableGrid = Grid<> # the initializer to use for collections in the builder [immutable.builder.init] Collection = ImmutableList.of() List = ImmutableList.of() Set = ImmutableSet.of() SortedSet = ImmutableSortedSet.of() Map = ImmutableMap.of() SortedMap = ImmutableSortedMap.of() EnumSet = ImmutableSet.of() NavigableSet = new TreeSet<>() NavigableMap = new TreeMap<>() BiMap = ImmutableBiMap.of() Multimap = ImmutableMultimap.of() ListMultimap = ImmutableListMultimap.of() SetMultimap = ImmutableSetMultimap.of() Multiset = ImmutableMultiset.of() SortedMultiset = ImmutableSortedMultiset.of() Table = ImmutableTable.of() Grid = ImmutableGrid.of() ImmutableCollection = ImmutableList.of() ImmutableList = ImmutableList.of() ImmutableSet = ImmutableSet.of() ImmutableSortedSet = ImmutableSortedSet.of() ImmutableMap = ImmutableMap.of() ImmutableSortedMap = ImmutableSortedMap.of() ImmutableBiMap = ImmutableBiMap.of() ImmutableMultimap = ImmutableMultimap.of() ImmutableListMultimap = ImmutableListMultimap.of() ImmutableSetMultimap = ImmutableSetMultimap.of() ImmutableMultiset = ImmutableMultiset.of() ImmutableSortedMultiset = ImmutableSortedMultiset.of() ImmutableTable = ImmutableTable.of() ImmutableGrid = ImmutableGrid.of() # the code used to copy varargs [immutable.builder.varargs] Collection = ImmutableList.copyOf($value) List = ImmutableList.copyOf($value) Set = ImmutableSet.copyOf($value) SortedSet = ImmutableSortedSet.copyOf($value) EnumSet = EnumSet.copyOf(Arrays.asList($value)) ImmutableCollection = ImmutableList.copyOf($value) ImmutableList = ImmutableList.copyOf($value) ImmutableSet = ImmutableSet.copyOf($value) ImmutableSortedSet = ImmutableSortedSet.copyOf($value) # provide the ability to handle clone-on-get for immutable classes [immutable.get.clone] Date = cloneCast Object[] = clone String[] = clone byte[] = clone char[] = clone short[] = clone int[] = clone long[] = clone float[] = clone double[] = clone boolean[] = clone Object[][] = cloneArray String[][] = cloneArray byte[][] = cloneArray char[][] = cloneArray short[][] = cloneArray int[][] = cloneArray long[][] = cloneArray float[][] = cloneArray double[][] = cloneArray boolean[][] = cloneArray # types that invalid in immutable beans [immutable.invalid.type] StringBuilder = StringBuffer = ConcurrentMap = ConcurrentNavigableMap = ArrayList = LinkedList = HashSet = TreeSet = HashMap = TreeMap = ConcurrentHashMap = ConcurrentSkipListMap = EnumBiMap = EnumHashBiMap = HashBiMap = EnumMultiset = HashMultiset = LinkedHashMultiset = TreeMultiset = ArrayListMultimap = LinkedListMultimap = HashMultimap = LinkedHashMultimap = TreeMultimap = # no immutable version of SortedSetMultimap # can be simulated via ImmutableSetMultimap.Builder, but complex SortedSetMultimap = ArrayTable = HashBasedTable = TreeBasedTable = SparseGrid = DenseGrid = Bean = FlexiBean = StrBuilder = ================================================ FILE: src/main/resources/org/joda/beans/gen/jdk.ini ================================================ #copies using JDK 6 classes only # how to copy $value to make it immutable [immutable.builder.to.immutable] Collection = Collections.unmodifiableCollection(new ArrayList<>($value)) List = Collections.unmodifiableList(new ArrayList<>($value)) Set = Collections.unmodifiableSet(new HashSet<>($value)) Map = Collections.unmodifiableMap(new HashMap<>($value)) SortedMap = Collections.unmodifiableSortedMap(new TreeMap<>($value)) EnumSet = EnumSet.copyOf($value) ImmutableBean = $value # how to copy $value to make it mutable [immutable.builder.to.mutable] Collection = new ArrayList<>($value) List = new ArrayList<>($value) Set = new HashSet<>($value) Map = new HashMap<>($value) SortedMap = new TreeMap<>($value) EnumSet = new HashSet<>($value) ImmutableBean = $value # the type to use for in the builder [immutable.builder.type] EnumSet = Set<> # the initializer to use for collections in the builder [immutable.builder.init] Collection = Collections.emptyList() List = Collections.emptyList() Set = Collections.emptySet() Map = Collections.emptyMap() SortedMap = new TreeMap<>() EnumSet = Collections.emptySet() # the code used to copy varargs [immutable.builder.varargs] Collection = Arrays.asList($value) List = Arrays.asList($value) Set = new LinkedHashSet<>(Arrays.asList($value)) SortedSet = new TreeSet<>(Arrays.asList($value)) EnumSet = EnumSet.copyOf(Arrays.asList($value)) # provide the ability to handle clone-on-get for immutable classes [immutable.get.clone] Date = cloneCast Object[] = clone String[] = clone byte[] = clone char[] = clone short[] = clone int[] = clone long[] = clone float[] = clone double[] = clone boolean[] = clone Object[][] = cloneArray String[][] = cloneArray byte[][] = cloneArray char[][] = cloneArray short[][] = cloneArray int[][] = cloneArray long[][] = cloneArray float[][] = cloneArray double[][] = cloneArray boolean[][] = cloneArray # types that invalid in immutable beans [immutable.invalid.type] StringBuilder = StringBuffer = ConcurrentMap = ConcurrentNavigableMap = ArrayList = LinkedList = HashSet = SortedSet = NavigableSet = NavigableMap = TreeSet = HashMap = TreeMap = ConcurrentHashMap = ConcurrentSkipListMap = Multimap = ListMultimap = SetMultimap = Multiset = SortedMultiset = ImmutableCollection = ImmutableList = ImmutableSet = ImmutableSortedSet = ImmutableMap = ImmutableSortedMap = ImmutableBiMap = ImmutableMultimap = ImmutableListMultimap = ImmutableSetMultimap = ImmutableMultiset = ImmutableSortedMultiset = Bean = FlexiBean = StrBuilder = ================================================ FILE: src/site/markdown/enterprise.md ================================================ ## Joda-Beans for Enterprise ### Available as part of the Tidelift Subscription **Tidelift** is working with the maintainers of **Joda-Beans** and thousands of other open source projects to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. ### Enterprise-ready open source software - managed for you The Tidelift Subscription is a managed open source subscription for application dependencies covering millions of open source projects across JavaScript, Python, Java, PHP, Ruby, .NET, and more. Your subscription includes: * **Security updates**
Tidelift’s security response team coordinates patches for new breaking security vulnerabilities and alerts immediately through a private channel, so your software supply chain is always secure. * **Licensing verification and indemnification**
Tidelift verifies license information to enable easy policy enforcement and adds intellectual property indemnification to cover creators and users in case something goes wrong. You always have a 100% up-to-date bill of materials for your dependencies to share with your legal team, customers, or partners. * **Maintenance and code improvement**
Tidelift ensures the software you rely on keeps working as long as you need it to work. Your managed dependencies are actively maintained and we recruit additional maintainers where required. * **Package selection and version guidance**
We help you choose the best open source packages from the start—and then guide you through updates to stay on the best releases as new issues arise. * **Roadmap input**
Take a seat at the table with the creators behind the software you use. Tidelift’s participating maintainers earn more income as their software is used by more subscribers, so they’re interested in knowing what you need. * **Tooling and cloud integration**
Tidelift works with GitHub, GitLab, BitBucket, and more. We support every cloud platform (and other deployment targets, too). The end result? All of the capabilities you expect from commercial-grade software, for the full breadth of open source you use. That means less time grappling with esoteric open source trivia, and more time building your own applications—and your business. [1]: https://tidelift.com/subscription/pkg/maven-org-joda-joda-beans?utm_source=maven-org-joda-joda-beans&utm_medium=referral&utm_campaign=enterprise [2]: https://tidelift.com/subscription/request-a-demo?utm_source=maven-org-joda-joda-beans&utm_medium=referral&utm_campaign=enterprise ================================================ FILE: src/site/markdown/index.md ================================================ ## About **Joda-Beans** provides a small framework that adds properties to Java, greatly enhancing JavaBeans. The key concept is to allow each property on a bean to be accessed as an object in its own right. This provides the hook for other technologies to build on, such as serialization, mapping, expression languages and validation. Joda-Beans is licensed under the business-friendly [Apache 2.0 licence](licensecover.html). ## Features A selection of key features: * Code generate mutable and immutable beans * No more manually written getters, setters, equals, hashCode, toString or immutable builders * High quality generated code, perfect for use in an API or for creating Javadoc * Full-featured property abstraction, treating a bean as a map of properties * Fast, no use of reflection * Built in JSON, XML and binary serialization ## Documentation Various documentation is available: * The helpful [user guide](userguide.html) * The extended [code generation guide](userguide-codegen.html) * The [Javadoc](apidocs/index.html) * The [change notes](changes-report.html) for each release * The [GitHub](https://github.com/JodaOrg/joda-beans) source repository * The [related projects](related.html) including Maven, Gradle and IntelliJ integration --- ## Why Joda Beans? Joda-Beans has been created to plug a gap in the Java language - properties. The concept of properties is familiar to those coding in almost every other modern language. Java stands alone in its pursuit of the JavaBeans, a specification built on naming conventions and reflection. JavaBeans are typically created by manual coding or one-off IDE generation, such as by Eclipse. The same approach is taken to the creation of equals and hashCode methods. However, none of these approaches provides for a simple and fast mechanism to query a bean for the properties it exposes. Joda-Beans provides a solution. As a developer, you just write the fields much as you would today. Then you add annotations to the bean and properties. Finally, you run a code generator, which creates the get/set methods plus framework methods that allow the properties to be effectively queried. A key point is that the code generator may be run again and again on the Java file, and is non-destructive. ``` @BeanDefinition public final class Foo implements Bean { /** The forename. */ @PropertyDefinition private String forename; /** The surname. */ @PropertyDefinition(validate = "notNull") private String surname; /** The address of the person. */ @PropertyDefinition private Address address; // Joda-Beans will code generate all getters, setters, equals, hashCode, toString and property accessors } ``` See these sample classes used for testing - [a simple user account class](https://github.com/JodaOrg/joda-beans/blob/v2.0/src/test/java/org/joda/beans/gen/UserAccount.java#L32), [example usage](https://github.com/JodaOrg/joda-beans/blob/v2.0/src/test/java/org/joda/beans/Examples.java#L22), [example of validation](https://github.com/JodaOrg/joda-beans/blob/v2.0/src/test/java/org/joda/beans/gen/ValidateBean.java#L33). As well as mutable beans following the Java Bean specification. Joda-Beans supports the creation of immutable beans. One of the biggest issues with using immutable objects in Java is their creation. Joda-Beans simplifies this by code generating builder classes for each immutable bean: ``` // using code generated immutable bean builders, example showing an interest rate swap leg FixedRateSwapLeg payLeg = FixedRateSwapLeg.builder() .accrualPeriods(PeriodicScheduleDefn.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(Frequency.P6M) .businessDayAdjustment(BusinessDayConventions.MODIFIED_FOLLOWING) .startDateBusinessDayAdjustment(BusinessDayAdjustment.NONE) .build()) .calculation(FixedRateCalculation.builder() .notional(CurrencyAmount.of(Currency.USD, 100_000_000)) .dayCount(DayCounts.THIRTY_U_360) .rate(0.015) .build()) .build(); ``` Once beans and properties are defined, it is possible to use them in powerful ways. A fast and efficient serialization mechanism is provided to read and write JSON, XML and binary using [Joda-Convert](/joda-convert/) for object to string conversion. Further integration is included for MongoDB and Freemarker. --- ## Releases The 3.x branch (v3.0.0-SNAPSHOT) is compatible with Java SE 21 or later. The 2.x branch (v2.11.1) is compatible with Java SE 8 or later. v3.x releases are mostly compatible with v2.x releases, see the [releases notes](changes-report.html) for details. Deprecated methods have been removed. Joda-Beans depends on [Joda-Convert](/joda-convert/). There are a number of [optional dependencies](dependencies.html) which help with integration. Available in [Maven Central](https://search.maven.org/search?q=g:org.joda%20AND%20a:joda-beans&core=gav). [GitHub release bundles](https://github.com/JodaOrg/joda-beans/releases). ```xml org.joda joda-beans 2.11.1 ``` For Java SE 6 compatibility, use [release 1.14](https://github.com/JodaOrg/joda-beans/releases/tag/v1.14). There are only [minor incompatibilities](migration.html) with the 1.x codebase. Note that the v2.x branch is based on Java 8 but contains a `module-info.class` file for Java 9 (using the multi-release jar format). See the [related projects](related.html) page for Maven, Gradle and IntelliJ integration. Java module name: `org.joda.beans`. --- ### For Enterprise [Available as part of the Tidelift Subscription](https://tidelift.com/subscription/pkg/maven-org-joda-joda-beans?utm_source=maven-org-joda-joda-beans&utm_medium=referral&utm_campaign=enterprise). Joda and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. If you want the flexibility of open source and the confidence of commercial-grade software, this is for you. [Learn more](https://tidelift.com/subscription/pkg/maven-org-joda-joda-beans?utm_source=maven-org-joda-joda-beans&utm_medium=referral&utm_campaign=enterprise). ### Support Please use [Stack Overflow](https://stackoverflow.com/search?q=joda-beans) for general usage questions. GitHub [issues](https://github.com/JodaOrg/joda-beans/issues) and [pull requests](https://github.com/JodaOrg/joda-beans/pulls) should be used when you want to help advance the project. Any donations to support the project are accepted via [OpenCollective](https://opencollective.com/joda). To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. ================================================ FILE: src/site/markdown/licensecover.md ================================================ ## License information Joda-Beans source code is released under the business-friendly [Apache 2.0 license](licenses.html). This is the same license as all [Apache Software Foundation](https://www.apache.org) projects. As is normal with the Apache 2.0 license, a NOTICE file exists for Joda-Beans: ``` Joda Beans Copyright 2001-present Stephen Colebourne This product includes software developed by Joda.org (https://www.joda.org/). ``` ================================================ FILE: src/site/markdown/migration.md ================================================ ## Migration to v2.0 Joda-Beans v2.0 has some incompatible changes. ### BeanQuery The `BeanQuery` interface has been removed. It was rarely used and can be better achieved via lambdas and functional interfaces in Java SE 8. The `ChainedBeanQuery` class is removed, with some behaviour replaced by `JodaBeanUtils.chain()`. ### PropertyMap The `PropertyMap` interface has been removed. It was rarely used and can be better achieved via `JodaBeanUtils.flatten()` or `BasicPropertyMap.of()`. ## BeanBuilder generics The method `BeanBuilder.get(MetaProperty)` has changed its generics. It you use it or have written a `BeanBuilder` you may be affected. ## BeanBuilder setString() and setAll() Applications should use Joda-Convert directly for the setString() methods and loop for setAll(). ### Registering meta-beans The `JodaBeanUtils.registerMetaBean()` and `JodaBeanUtils.metaBean()` methods have been deprecated. Use `MetaBean.register()` and `MetaBean.of()` instead. ## Config file The config file "jdk6.ini" has been renamed to "jdk.ini". The old name is recognised on the command line. ## Light and Minimal beans The code generation strategies have been altered to be simpler. They are now ready for Java SE 9. ## Reflective beans The factory method has been changed. The meta-bean now takes all the property names. This avoids the need to use reflection to find the meta-properties, ready for Java SE 9. ================================================ FILE: src/site/markdown/related.md ================================================ ## Related projects Here are links to a number of projects related to **Joda-Beans**. These projects are independent - no guarantees of quality are given! * [Maven plugin](https://github.com/JodaOrg/joda-beans-maven-plugin) by Stephen Colebourne * [Gradle plugin](https://github.com/andreas-schilling/joda-beans-gradle-plugin) by Andreas Schilling * [Eclipse integration](https://github.com/JodaOrg/joda-beans-maven-plugin) via Maven plugin and M2E * [IntelliJ code folding](https://github.com/cjkent/jodabeansfolding) by Chris Kent * [UI generator](https://github.com/JodaOrg/joda-beans-ui) by Stephen Colebourne * [Integration projects](https://github.com/JodaOrg/joda-beans-integrate) for Freemarker, Kryo and Mongo If your open source library provides a value added feature on top of Joda-Beans, then let us know! Just send a pull request to edit this page. ================================================ FILE: src/site/markdown/userguide-codegen.md ================================================ ## User guide - Code generation This part of the user guide provides information on code generation of beans. See the [main user guide](userguide.html) for a higher level introduction. ## Code generator It is possible to write a Joda-Bean by hand - they are just normal Java interfaces defining an API for beans. There are some base classes that assist as well as some standard map-based implementations, notably [FlexiBean](apidocs/org.joda.beans/org/joda/beans/impl/flexi/FlexiBean.html). It is more common to use the code generator, however the generator is optional. A code generated Joda-Bean minimises the amount of code that the developer has to write. The developer simply creates an outline class and adds the properties (fields). The code generator then produces all the getters and setters, plus additional helper methods. Here is an example `UserAccount` class showing the parts that a developer has to write: ```java @BeanDefinition public final class UserAccount implements Bean { /** The user identifier. */ @PropertyDefinition(validate = "notEmpty") private String userId; /** The email address. */ @PropertyDefinition(validate = "notEmpty") private String emailAddress; /** The number of logins. */ @PropertyDefinition private int numberLogins; /** The last login instant. */ @PropertyDefinition(validate = "notNull") private Date lastLogin; } ``` The code generator will create getters, setters, equals, hashCode, toString, metaBean and properties. To see the generated code for this class, [click here](https://github.com/JodaOrg/joda-beans/blob/v1.4/src/test/java/org/joda/beans/gen/UserAccount.java#L34). Note that the equals, hashCode and toString methods are only generated if they do not exist already. As such, it is easy to write your own versions of these methods if necessary. The restriction is that you must write your own version of these methods *before* the autogenerated block. Any equals, hashCode or toString method after the autogenerated block will be ignored (because they might be part of a nested class). ## Using the code generator The code generator must be invoked before compilation as it generates Java source code. It cannot operate at runtime, as the getters and setters that are generated must be available for developers writing the main part of the application. The code generator operates by creating a portion of the source file marked by "AUTOGENERATED START" and "AUTOGENERATED END" tags (when first run, if the tags are not present, it will create the block at the end of the file). The generator only ever changes code within the marked block, apart from imports which it inserts if it determines they are necessary. Limiting the generation to a fixed part of the file means that developers can customise the rest of the Java file in any way that is desired, such as adding constructors and methods. The generator has the following requirements: * The class must be annotated with [BeanDefinition](apidocs/org.joda.beans/org/joda/beans/gen/BeanDefinition.html) * The class must directly implement the [Bean](apidocs/org.joda.beans/org/joda/beans/Bean.html) or [ImmutableBean](apidocs/org.joda.beans/org/joda/beans/ImmutableBean.html) interface. * The class must be a normal top-level class, nested/inner classes and multiple classes per file are not supported * Each property field must be annotated with [PropertyDefinition](apidocs/org.joda.beans/org/joda/beans/gen/PropertyDefinition.html) * Each property field must be be private * The Javadoc of each property field should normally start with the word "The". The command line takes the following arguments: ``` Usage java org.joda.beans.gen.BeanCodeGen [file] Options -R process all files recursively, default false -indent=tab use a tab for indenting, default 4 spaces -indent=[n] use n spaces for indenting, default 4 -prefix=[p] field prefix of p should be removed, no default -eol=[e] end of line: 'lf'/'crlf'/'cr', default System.lineSeparator -generated add @Generated annotation to generated code -config=[f] config file: 'jdk'/'guava', default guava -style=[s] default bean style: 'light'/'minimal'/'full', default smart -verbose=[v] output logging with verbosity from 0 to 3, default 1 -nowrite output messages rather than writing, default is to write ``` The prefix is useful for teams that have a coding standard where fields must be prefixed, such as by an underscore or a letter. Specifying it to the generator allows that prefix to be stripped before generating the property name. The eol argument allows for configuring the line separator used to write generated files. The code generator works by reading the source file and parsing it to memory. The parser is deliberately simplistic and will reject complex files or unusual code formatting styles. The generator processes the annotated properties and replaces the auto-generated section of the file in memory. It then compares the newly generated file with the original and only if they are different is the new file written to the file system. The generator will make use of property comments and will respect and propagate deprecated annotations. It is reasonably intelligent - final fields will become read-only properties, most collections and maps are sensibly handled and booleans generate "is" methods rather than "get" methods. Simple generics are also handled. The generator must be invoked every time that the source file is changed. Failure to do so (such as by using an IDE refactoring) could leave the auto-generated block in an invalid state. Normally the generator will be invoked from the IDE or a build tool, see the [Maven plugin](https://github.com/JodaOrg/joda-beans-maven-plugin). The code generator only parses and outputs based on a single source Java file. It does not require the file to compile and never knows that "String" actually means "java.lang.String". In other words, the type system in the generator is totally dumb and based solely on the short simple class name. ## Customisation The generator has a limited set of customisations to the core part of the generation. One key set of control is provided by [@PropertyDefinition](apidocs/org.joda.beans/org/joda/beans/gen/PropertyDefinition.html). The style of getter can be controlled using the annotation parameter "get". In most cases, the default "smart" setting is sufficient: * "" - do not generate any form of getter * "smart" - process intelligently, using "is" for `boolean` and "get" for other types * "private" - process as per "smart" but set scope as private * "package" - process as per 'smart' but set scope as package/default * "protected" - process as per "smart" but set scope as protected * "is" - generates `isXxx()` * "get" - generates `getXxx()` * "clone" - generates `getXxx()` with a clone of the field (assumed to be of the correct type) * "cloneCast" - generates `getXxx()` with a clone of the field with a cast to the property type * "cloneArray" - generates getXxx() with a deep clone of the array suitable for multi-dimensional arrays * "optional" - generate `getXxx()` returning a Java 8 `Optional` wrapper around the field, where the field itself is nullable instead of optional. `OptionalDouble`, `OptionalInt` and `OptionalLong` are also handled * "optionalGuava" - generate `getXxx()` returning a Guava `Optional` wrapper around the field, where the field itself is nullable instead of optional * "field" - generates direct access to the field, enabling a weird manual getter * "manual" - a method named `getXxx()` must be manually provided For example, using the optional wrappers: ```java @BeanDefinition public final class Foo implements Bean { @PropertyDefinition(get = "optional") private String name; // regular field that can hold null // generated getter as follows: public Optional getName() { return Optional.ofNullable(name); } } ``` The style of setter can be controlled using the annotation parameter "set". In most cases, the default "smart" setting is sufficient: * "' - do not generate any form of setter * "smart" - process intelligently - uses "set" unless final, when it will use "setClearAddAll" for common list types or "setClearPutAll" for common map types and `FlexiBean` * "private" - process as per "smart" but set scope as private * "package" - process as per 'smart' but set scope as package/default * "protected" - process as per "smart" but set scope as protected * "set" - generates `setXxx()` * "setClearAddAll" - generates `setXxx()` using `field.clear()` and `field.addAll(newData)` * "setClearPutAll" - generates `setXxx()` using `field.clear()` and `field.putAll(newData)` * "cloneArray" - generates setXxx() with a deep clone of the array suitable for multi-dimensional arrays * "bound" - generates a bound property with {@code PropertyChangeSupport} * "field" - generates direct access to the field, enabling a weird manual setter * "manual" - a method named `setXxx()` must be manually provided at package scope or greater * a pattern, see [Javadoc](apidocs/org.joda.beans/org/joda/beans/gen/PropertyDefinition.html#set--) For example, to have a private setter: ```java @BeanDefinition public final class Foo implements Bean { @PropertyDefinition(set = "private") private String name; // generated setter as follows: private String setName() { this.name = name; } } ``` Note that support for bound properties is very basic. It only handles simple mutable properties. For more complex cases, it is necessary to write the setter manually. The PropertyChangeSupport field is generated, but not the methods to add listeners. Validation can be specified using the annotation parameter "validate": * "" - do not generate any form of validation * "notNull" - checks that the value is non-null using `JodaBeanUtils.notNull()` which throws IllegalArgumentException * "notEmpty' - checks that a string/collection/map is non-null and non-empty using `JodaBeanUtils.notEmpty()` which throws IllegalArgumentException * "{staticMethodName}" - a custom validation method located on this class * "{className}.{staticMethodName}" - a custom validation method located on any class ```java @BeanDefinition public final class Foo implements Bean { @PropertyDefinition(validate = "notNull") private String surname; // generated code will ensure field is non-null } ``` The exposed type of the property can be specified using the annotation parameter "type". For example, if the field is declared as an `ArrayList` but the public type of the getter/setter should be `List` then that can be achieved. Simply add the annotation parameter `type = "List<>"` (the generics are inserted during generation). ```java @BeanDefinition public final class Foo implements Bean { @PropertyDefinition(type = "List<>") private ArrayList names; // generated getter as follows: public List getNames() { ... } } ``` The exposed type of the property in the builder used for immutable beans can be specified using the annotation parameter "builderType". For example, if the field is declared as an `ImmutableList

` but the public type of the builder methods should be `List` then that can be achieved. Simply add the annotation parameter `builderType = "List"`. ```java @BeanDefinition public final class Foo implements Bean { @PropertyDefinition(builderType = "List") private ImmutableList
addresses; // generated getter as follows: public ImmutableList
getAddresses() { ... } // generated builder method as follows: public Builder addresses(List addresses) { ... } } ``` A properties getter and/or setter can be declared to override a superclass. Simply add the annotation parameter `overrideGet = true` or `overrideSet = true` and the requisite `@Override` annotation will be placed on the getter/setter. ```java @BeanDefinition public final class Foo implements Bean { @PropertyDefinition(overrideGet = true) private String name; // generated getter as follows: @Override public String getName() { ... } } ``` A property can be given an alias, or alternate name. Simply add the annotation parameter `alias = "otherName"`. This is most useful when a property is renamed, to handle change during [deserialization](userguide-serialization.html). The style of equals/hashCode/toString can be controlled using the annotation parameters "equalsHashCodeStyle" and "toStringStyle". In most cases, the default "smart" setting is sufficient: * "omit" - omit this property from equals/hashCode/toString * "smart" - process intelligently, equivalent to "field" for immutable and "getter" for mutable * "getter" - use the getter for equals/hashCode/toString * "field" - use the field for equals/hashCode/toString ## Derived properties It is possible to declare a property without a matching field. For example, an "age" property could be derived from a "dateOfBirth" field. To do this, annotate the getter of the derived property with [DerivedProperty](apidocs/org.joda.beans/org/joda/beans/gen/DerivedProperty.html). Apart from the absence of a field, a derived property is very similar to a normal read-only property. ## Immutable beans Code generated beans may be immutable. All fields in an immutable bean must be final. It is recommended that immutable beans are final, do not extend any other bean class and directly implement [ImmutableBean](apidocs/org.joda.beans/org/joda/beans/ImmutableBean.html). ```java @BeanDefinition public final class Foo implements ImmutableBean { // code generated immutable bean with public builder } ``` Certain configuration settings will not work as expected if an immutable bean is not declared as final. ### Immutable bean customisation Code generated immutable beans can be customized as follows. An immutable bean can be configured to provide additional cross-property validation. In most cases the per-property validation attribute is sufficient. When cross-property validation is needed, this technique can be used. Simply declare a private void method taking no arguments annotated with [@ImmutableValidator](apidocs/org.joda.beans/org/joda/beans/gen/ImmutableValidator.html). The method will be called during the validation phase of the constructor. ```java @ImmutableValidator private void validate() { // validate the instance variables of the bean } ``` An immutable bean can be configured to apply default property values. In most cases this is not necessary, but if the bean has lots of non-null properties it may be desirable to have some default values. Simply declare a private static void method taking one 'Builder' argument annotated with [@ImmutableDefaults](apidocs/org.joda.beans/org/joda/beans/gen/ImmutableDefaults.html). The method will be called before the empty builder is made available for population. ```java @ImmutableDefaults private static void applyDefaults(Builder builder) { // set default property values directly into the builder } ``` An immutable bean can be intercepted when the bean is being built. In most cases this is not necessary, but if the bean has a property that needs to be defaulted from another property this can be useful. In general, use of `@ImmutableValidator` and/or `@ImmutableDefaults` should be preferred. Simply declare a private static void method taking one 'Builder' argument annotated with [@ImmutablePreBuild](apidocs/org.joda.beans/org/joda/beans/gen/ImmutablePreBuild.html). The method will be called when `build()` is invoked on the builder. ```java @ImmutablePreBuild private static void preBuild(Builder builder) { // query the builder and make any necessary changes } ``` The constructor of an immutable bean can be replaced. In most cases this is not necessary, but there may be occasional use cases. In general, use of `@ImmutableValidator` and/or `@ImmutableDefaults` should be preferred. A constructor with parameters matching each property must be written and annotated with [@ImmutableConstructor](apidocs/org.joda.beans/org/joda/beans/gen/ImmutableConstructor.html). It may be easier to generate the bean without the annotation and move the generated constructor out into user code, adding the annotation only at that point. ```java @ImmutableConstructor private MyBean(String surname, String forename) { // a constructor entirely under application control } ``` An immutable bean can be configured to cache the hash code. In most cases this is not necessary, but if the bean is used as a hash key, then it may be helpful. Simply set the boolean 'cacheHashCode' flag of '@BeanDefinition' to true. ```java @BeanDefinition(cacheHashCode = true) public final class Foo implements ImmutableBean { // code generated immutable bean with cached hash code } ``` Immutable beans do not have set methods. Instead, a public builder class will be generated with methods to setup an instance. This supports code based manipulation, using the `toBuilder()` method. The scope of the builder, public private or package-scoped, may be controlled in the bean definition. The default is public for immutable beans and no-builder for mutable beans: ```java @BeanDefinition(builderScope = "private") public final class Bar implements ImmutableBean { // code generated immutable bean with private builder } ``` A static factory may be created for an immutable bean. This may be instead of or in addition to the builder. The scope of the factory is always public, and it always contains all properties. Any additional customisation should involve moving the generated factory outside the autogenerated block. To create the factory, specify the method name: ```java @BeanDefinition(factoryName = "of") public final class Bar implements ImmutableBean { // code generated immutable bean with static factory named "of" } ``` The scope of the meta-bean, public private or package-scoped, may also be controlled in the bean definition. The default is public: ```java @BeanDefinition(metaScope = "package") public final class Bar implements ImmutableBean { // code generated immutable bean with package-scoped meta-bean } ``` The scope of the generated constructor for immutable beans can be controlled. The default is to be as private as possible for the needs of the builder, typically private: ```java @BeanDefinition(constructorScope = "package") public final class Bar implements ImmutableBean { // code generated immutable bean with package-scoped constructor } ``` An option also exists to generate the ConstructorProperties annotation: ```java @BeanDefinition(constructorScope = "public@ConstructorProperties") public final class Bar implements ImmutableBean { // code generated immutable bean with annotated public constructor } ``` A user-defined interface can be added to the meta-bean using the bean definition: ```java @BeanDefinition(metaImplements = "ShapeMeta") public final class Square implements Shape, ImmutableBean { // code generated meta-bean that implements ShapeMeta } ``` ## Immutable bean hierarchies It is possible for an immutable bean to be non-final. Any subclass should logically also be immutable, but must set the `BeanDefinition` annotation value `hierarchy` to "immutable": ```java // superclass @BeanDefinition public abstract class SuperFoo implements ImmutableBean { // code generation will enable an immutable subclass } // subclass @BeanDefinition(hierarchy = "immutable") public final class Foo extends SuperFoo { // code generation will connect to superclass // note that there is NO 'implements ImmutableBean' on the subclass } ``` It is also possible for a bean to be partially final. In this case, the bean will implement `Bean` rather than `ImmutableBean`. To get the correct behaviour, the `BeanDefinition` annotation value `builderScope` must be set to "public". Partially final beans can extend one another, but must all declare the builder scope. The rules as to what works and what does not are complex. It is recommended to keep is simple, and only have normal mutable beans or final immutable beans. ## Light beans It is possible to generate a very light-weight bean. This approach has no Meta class or Builder (the objects exist behind the scenes). This is the approach with the lowest code generation. ```java // superclass @BeanDefinition(style = "light") public final class LightBean implements ImmutableBean { // code generation of a light-weight immutable bean } ``` Internally, the bean uses reflection to implement the meta bean and builder. As such, it may be a little slower. Both immutable and mutable light-weight beans can be generated. ## Minimal beans It is possible to generate a minimal bean. This approach has no Meta class, but does have a Builder for immutable classes. This is the approach with the medium amount of code generation. ```java // superclass @BeanDefinition(style = "minimal") public final class MinimalBean implements ImmutableBean { // code generation of a minimal immutable bean } ``` Internally, the bean uses lambdas to implement the meta bean. Both immutable and mutable minimal beans can be generated. ## Manual builders It is possible to write the builder class manually and still have the generated code refer to it. A manual builder can be an inner class or top-level class. ```java @BeanDefinition(builderName = "PersonBuilder", constructorScope = "package") public final class Person implements ImmutableBean { // code generation of a minimal immutable bean } // using `extends BasicImmutableBeanBuilder` might be a better place to start public final class PersonBuilder implements BeanBuilder { // manual builder code } ``` A common way to approach manual builders is to generate the builder, copy the builder code, add the `builderName` flag and paste the builder code ready to edit. ## Test coverage Code generated beans are great, but they have a side effect of creating lots of untested generated code. This can make the test coverage percentage produced by tools seem very low. One solution to this is provided by the `JodaBeanTests` class which provides methods to artificially provide test coverage. Of course, this can be used for good or evil! The intention is that it is used to highlight those parts of the codebase that really do need tests, not to stop you needing tests at all. ## Links Return to the [main user guide](userguide.html). ================================================ FILE: src/site/markdown/userguide-serialization.md ================================================ ## User guide - Serialization This part of the user guide provides information on serialization of beans. See the [main user guide](userguide.html) for a higher level introduction. ## Serialization The `org.joda.beans.ser` package provides support for serializing Joda-Beans via JSON, XML or MsgPack binary. The main class is [JodaBeanSer](apidocs/org.joda.beans/org/joda/beans/ser/JodaBeanSer.html). It contains the relevant settings and methods to access the serialization and deserialization. The serializer makes use the meta-data in the bean to minimize the output size. In effect, the Joda-Bean acts as a schema to interpret the data. Two standard layouts are provided - COMPACT and PRETTY. The compact layout has no whitespace, whereas the pretty layout uses indentation and new-lines. Methods on `JodaBeanSer` allow for further customization. ### XML ```java // write to XML String xmlStr = JodaBeanSer.COMPACT.xmlWriter().write(bean); // read from XML MyBean bean = JodaBeanSer.COMPACT.xmlReader().read(xmlStr, MyBean.class); ``` ### JSON ```java // write to JSON String jsonStr = JodaBeanSer.COMPACT.jsonWriter().write(bean); // read from JSON MyBean bean = JodaBeanSer.COMPACT.jsonReader().read(jsonStr, MyBean.class); ``` There is also a simple JSON reader/writer that does not expose Java types. ### Binary For binary there are three different formats available: * `binReader(STANDARD)` is the default and suitable for most uses. * `binReader(REFERENCING)` deduplicates all beans it sees, which can be slow. * `binReader(PACKED)` is the effective replacement for REFERENCING where callers choose which beans to deduplicate. The classes to deduplicate can be controlled in the PACKED format using `JodaBeanSer.withBeanValueClasses()`. ```java // write to Binary var bytes = JodaBeanSer.COMPACT.binWriter(JodaBeanBinFormat.PACKED).write(bean); // read from Binary MyBean bean = JodaBeanSer.COMPACT.binReader().read(bytes, MyBean.class); ``` Note that COMPACT vs PRETTY makes no difference in binary mode. ## Supported types The serialization mechanism supports implementations of `Bean`, `Collection`, `Map`, `Optional` and arrays. Some formats also support `Iterable`. If Guava is present, implementations of `Multimap`, `Multiset`, `Table`, `BiMap` and Guava's `Optional` are supported. If Joda-Collect is present, implementations of `Grid` are supported. The serialization format is generally stable over different versions of the API. The following incompatibilities apply: * The simple JSON format in v3.x alters two-dimensional primitive arrays to be written using the natural format `[[1, 2], [2, 3]]` instead of the previous format `["1,2", "2,3"]`. * The standard binary format in v3.x adjusts two-dimensional primitive arrays in a similar way to JSON. * The binary formats in v3.x permit null keys in maps. ## Handling change When deserializing, the Joda-Bean meta-data is used to parse the input JSON/XML/binary. However, this causes a problem if the bean is refactored between serialization and deserialization. To handle this, three mechanisms are provided. Firstly, the `RenameHandler` class from Joda-Convert is used. This allows type renames and enum constant renames to be handled. The class is a singleton and must be configured at application startup. Secondly, Joda-Beans provides the `SerDeserializer` mechanism. A `SerDeserializer` class can be written for each refactored bean. It supports multiple kinds of change, including property rename, property type change and complex semantic changes. It is registered with `SerDeserializers` and called directly as part of the parsing process. Finally, the `PropertyDefinition` annotation has an "alias" attribute. Setting that allows the old name of a property to be retained when a property is renamed. ## Leniency The default deserialization mechanism is relatively strict. If the input contains an unknown property then an error will be thrown. Similarly, if a Java type is not handled by `SerTypeMapper` then an exception is thrown. There is an alternative mode that is more lenient: JodaBeanSer s = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); This mode will ignore unknown properties received for a bean. If a Java type cannot be found, lenient mode will attempt to fallback to an alternative type, such as `String`. Together these help solve problems when integrating multiple projects/services using Joda-Beans. ## Smart reader When reading data, it is possible to determine the type of the serialized data dynamically. Use `JodaBeanSer.COMPACT.smartReader()` to read an input stream that contains a JSON, XML or binary serialized bean. ## Links Return to the [main user guide](userguide.html). ================================================ FILE: src/site/markdown/userguide.md ================================================ ## User guide Joda-Beans is a small library that adds properties to the Java programming language. It consists of these main parts: * a set of interfaces and classes that define a property * a source [code generator](userguide-codegen.html) * [serialization and deserialization](userguide-serialization.html) via JSON, XML and MsgPack binary * integration with other technologies The main rationale for the project is to raise the abstraction level of Java development. Most mainstream languages have some kind of support for properties, unfortunately Java does not. The benefits of the Joda-Beans approach mostly apply when using the code generator: * easy to write common utilities acting on arbitrary beans without using reflection * no need to manually write getters, setters, equals, hashCode, toString * simple way to create immutable beans * effective and simple round-trip serialization and deserialization ## Bean and Property model The Joda-Bean API is based around a model of properties in the Java programming language. All beans implement the [Bean](apidocs/org.joda.beans/org/joda/beans/Bean.html) interface. This defines a minimal API for all beans, providing the ability to obtain the property names and a named property. The interface also provides access to the *meta-bean*. The [MetaBean](apidocs/org.joda.beans/org/joda/beans/MetaBean.html) interface defines the meta-bean. The "meta" name indicates that this is a higher level description of the bean itself. In fact, the meta-bean is the equivalent to `java.lang.Class` for beans - there is only one meta-bean object for all instances of the bean. The meta-bean API provides access to the name of the bean, it's type, a builder and the *meta-properties*. The [MetaProperty](apidocs/org.joda.beans/org/joda/beans/MetaProperty.html) interface is the main definition of a property. It is at the "meta" level, describing the property without holding a references to any specific instance of a bean. As such, it is effectively the equivalent to `java.lang.reflect.Field` for a single property on a bean - there is only one meta-property object for all instances of the property. The meta-property API provides access to the name of the property, it's type, any declared annotations and whether it is read-write or read-only. It also include methods to get and set the value, which require the bean to be passed in just like `java.lang.reflect.Field`. ``` Bean person = new Person(); MetaProperty surnameMetaProperty = bean.metaBean().metaProperty("surname"); String surname = surnameMetaProperty.get(person); ``` The bean itself also provides access to instances of the [Property](apidocs/org.joda.beans/org/joda/beans/Property.html) interface for each property. Each property object is a simple combination of the bean and the meta-property. This means that there are simple methods to get and set the value of the property which directly affect the underlying bean. The property also provides methods to get the property name, the underlying bean and the meta-property. ``` Bean person = new Person(); Property surnameProperty = bean.property("surname"); String surname = surnameProperty.get(); ``` ### Use in an application Applications can use Joda-Beans properties in many ways, revolving around passing a single property of an object to another method. For example, it would be possible to write a validating method that checked the validity of a single property, but perhaps registered errors on the underlying bean. ### Use in a framework Joda-Beans is designed to work well with frameworks which need dynamic access to the properties of a bean. It is recommended when working with a framework to primarily use the meta-bean and associated meta-properties. This is because they tend to be singletons and more efficient than using the property objects. The meta-property API is also more comprehensive than the property API. Beans are normal Java objects and can be created from scratch using constructors. Frameworks may wish to use the [BeanBuilder](apidocs/org.joda.beans/org/joda/beans/BeanBuilder.html) interface which provides a standard way to build the bean. The builder is obtained from the meta-bean. Each property is then set before calling `build`. A selection of utilities is available on [JodaBeanUtils](apidocs/org.joda.beans/org/joda/beans/JodaBeanUtils.html). This includes the ability to lookup a meta-bean from a `java.lang.Class`, access to the Joda-Convert string converter and methods to extract the types of lists and maps using reflection on generics. The access to the field-level annotations provided by the meta-property is also useful to framework writers. ### Joda-Convert integration A Joda-Beans meta-property provides the ability to set a property from a string. The conversion between the string and the type of the property, such as `int` or `URI`, is handled by [Joda-Convert](/joda-convert/). The converter can be customised, and is exposed by `JodaBeanUtils`. When iterating over a bean object graph, being able to determine which objects are "leaves", the simple types that have a direct string representation, is a very useful ability. ### Finding the generic type parameters of a property The Java bytecode format contains more details about generic types than is often realised. The `JodaBeanUtils` methods `collectionType()`, `mapKeyType()` and `mapValueType()` allow the generic parameter type of a property to be extracted. Thus an application can tell that a property is of type `List`, not just `List`. ### Iterating over a bean object graph The `JodaBeanUtils` class contains the method `beanIterator()`. This provides a simple mechanism to iterate over all the beans within a bean. The iteration is depth-first, and handles collections, and collections within collections. Note however that there is no protection against cycles in the object graph, thus the method is only fully safe when using immutable beans. ``` for (Bean bean : JodaBeanUtils.beanIterator(rootBean)) { // perform logic on each bean in the object graph } ``` ## Code generation It is entirely possible to write a Joda-Bean by hand - the design utilises simple Java interfaces. Most users choose to code generate beans however. For information on code generation, see the [code generation user guide](userguide-codegen.html). ## Serialization One of the benefits of a bean and property system is that serialization code becomes much simpler. For information on serialization in XML, JSON and binary, see the [serialization user guide](userguide-serialization.html). ## Integration Joda-Beans has been integrated with Freemarker, MongoDB and Kryo. The integration support classes are included in the jar file but only work when the optional dependency is present. Note that it is entirely valid to use Joda-Beans without additional jar file dependencies apart from Joda-Convert. The beans are also widely use in the [Strata](https://strata.opengamma.io/) market risk project. ================================================ FILE: src/site/resources/css/site.css ================================================ /* Fix broken definition that causes hyperlinks to break */ h1[id]:before, h2[id]:before, h3[id]:before, h4[id]:before, h5[id]:before, h6[id]:before, a[name]:before { height:0px; margin:0px; } /* Blacker text */ body { color: #222; } code, pre { color: #444; } .main-body p b { font-weight: bold; color: #722; } .dropdown-menu>li>a { color: #666; } /* Sidebar had too much padding at the top */ .well { padding-top: 6px; padding-bottom: 36px; } /* Font Awesome icons by CSS as markdown class is stripped */ h2 i { display: inline-block; font: normal normal normal 14px/1 FontAwesome; font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } h2#About i:before { content: "\f015"; } h2#Features i:before { content: "\f0d0"; } h2#Documentation i:before { content: "\f02d"; } h2#Releases i:before { content: "\f02c"; } h2#Why_Joda_Beans i:before { content: "\f19c"; } h2#Rationale i:before { content: "\f0eb"; } /* Enterprise page */ h2#Joda-Beans_for_Enterprise~div > p:last-child { text-align: center; margin-top: 1.1em; margin-bottom: 1.2em; } button.btn-learnmore, button.btn-requestdemo { width: 14em; font-size: 1.2em; text-align: center; padding-top: 0.3em; padding-bottom: 0.3em; border-radius: 3px; border-style: solid; } button.btn-learnmore { color: #f6914d; background-color: white; border-color: #f6914d; } button.btn-learnmore a { color: #f6914d; } button.btn-requestdemo { color: white; background-color: #f6914d; border-color: #f6914d; } button.btn-requestdemo a { color: white; } ================================================ FILE: src/site/resources/download.html ================================================ OpenGamma ================================================ FILE: src/site/site.xml ================================================ UA-1425975-4 org.joda.external reflow-maven-skin 1.2 false true github false bootswatch-cosmo Joda-Beans index.html Documentation|Releases|Development|Joda|For Enterprise Documentation Releases Development Reports false false false true 3 1 Home false false false false ]]> ================================================ FILE: src/test/java/org/joda/beans/Examples.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import org.joda.beans.sample.Address; import org.joda.beans.sample.Documentation; import org.joda.beans.sample.Person; /** * Examples using Person. */ public class Examples { public static void main(String[] args) { // create the bean the hard way - could just do new Person() instead Person p = Person.meta().builder().set("surname", "Smith").build(); // set surname using normal method p.setSurname("Colebourne"); // query using property method System.out.println(p.surname().get()); // query using meta-property method System.out.println(Person.meta().surname().get(p)); // set/get forename using property method p.forename().set("Stephen"); System.out.println(p.forename().get()); // set cars p.numberOfCars().set(2); // access all the properties System.out.println(p.propertyNames()); System.out.println(JodaBeanUtils.flatten(p)); System.out.println(p); // perform validation boolean valid = validateNotEmpty(p.surname()) && validateNotEmpty(p.forename()); System.out.println(valid ? "Valid" : "Not valid"); // extensions p.getExtensions().set("suffix", "Jr"); System.out.println(p.propertyNames()); System.out.println(JodaBeanUtils.flatten(p)); System.out.println(p); // create the bean the hard way - could just do new Address() instead Address a = Address.meta().builder().build(); // set surname using normal method a.setStreet("Barnsnap Close"); // query using property method System.out.println(a.street().get()); // set/get forename using property method a.city().set("Horsham"); System.out.println(a.city().get()); // set cars a.number().set(22); // access all the properties System.out.println(a.propertyNames()); System.out.println(JodaBeanUtils.flatten(a)); System.out.println(a); // perform validation valid = validateNotEmpty(a.street()) && validateNotEmpty(a.city()); System.out.println(valid ? "Valid" : "Not valid"); // generics Documentation
d = new Documentation<>(); d.setType("ADDRESS"); d.setContent(a); Property
dProp = d.content(); Address a2 = dProp.metaProperty().get(d); System.out.println(a2); Address a3 = Documentation.metaDocumentation(Address.class).content().get(d); System.out.println(a3); Documentation
d2 = Documentation.metaDocumentation(Address.class).builder().build(); System.out.println(d2); // try { // Mongo mongo = new Mongo("127.0.0.1"); // System.out.println(mongo); // mongo.dropDatabase("BeansTest"); // DB db = mongo.getDB("BeansTest"); // DBCollection coll = db.createCollection("Test", new BeanMongoDBObject(p)); // System.out.println(coll); // System.out.println("Docs " + coll.getCount()); // // } catch (Exception ex) { // ex.printStackTrace(); // } } private static boolean validateNotEmpty(Property property) { String str = property.get(); return (str != null && str.length() > 0); } } ================================================ FILE: src/test/java/org/joda/beans/TestAddress.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.sample.Address; import org.junit.jupiter.api.Test; /** * Test property using Person. */ class TestAddress { private static final int NUM_PROPERTIES = 4; private static final String STREET = "street"; private static final String CITY = "city"; private static final String NUMBER = "number"; @Test void test_bean() { Bean test = new Address(); assertThat(test).isInstanceOf(Address.class); assertThat(test.metaBean()).isEqualTo(Address.meta()); assertThat(test.propertyNames()).contains(STREET); assertThat(test.propertyNames()).contains(CITY); assertThat(test.propertyNames()).contains(NUMBER); assertThat(test.propertyNames()).doesNotContain("Rubbish"); assertThat(test.property(STREET).name()).isEqualTo(STREET); assertThat(test.property(CITY).name()).isEqualTo(CITY); assertThat(test.property(NUMBER).name()).isEqualTo(NUMBER); } @Test void test_bean_invalidPropertyName() { Bean test = Address.meta().builder().build(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.property("Rubbish")); } @Test void test_builder1() { BeanBuilder builder = Address.meta().builder(); builder.set("street", "Main Street"); assertThat(builder.get("street")).isEqualTo("Main Street"); builder.set("city", "London"); assertThat(builder.get("street")).isEqualTo("Main Street"); assertThat(builder.get("city")).isEqualTo("London"); String street = builder.get(Address.meta().street()); assertThat(street).isEqualTo("Main Street"); String city = builder.get(Address.meta().city()); assertThat(city).isEqualTo("London"); Address test = builder.build(); Address expected = new Address(); expected.setStreet("Main Street"); expected.setCity("London"); assertThat(test).isEqualTo(expected); } @Test void test_builder2() { BeanBuilder builder = Address.meta().builder(); builder.set(Address.meta().street(), "Main Street"); builder.set(Address.meta().number(), 12); Address test = builder.build(); Address expected = new Address(); expected.setStreet("Main Street"); expected.setNumber(12); assertThat(test).isEqualTo(expected); } @Test void test_builder_getInvalidPropertyName() { BeanBuilder builder = Address.meta().builder(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.get("Rubbish")); } @Test void test_builder_setInvalidPropertyName() { BeanBuilder builder = Address.meta().builder(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.set("Rubbish", "")); } //----------------------------------------------------------------------- @Test void test_metaBean() { MetaBean test = Address.meta(); assertThat(test.beanType()).isEqualTo(Address.class); assertThat(test.beanName()).isEqualTo(Address.class.getName()); assertThat(test.metaPropertyCount()).isEqualTo(NUM_PROPERTIES); assertThat(test.metaPropertyExists(STREET)).isTrue(); assertThat(test.metaPropertyExists(CITY)).isTrue(); assertThat(test.metaPropertyExists(NUMBER)).isTrue(); assertThat(test.metaPropertyExists("Rubbish")).isFalse(); assertThat(test.metaProperty(STREET).name()).isEqualTo(STREET); assertThat(test.metaProperty(CITY).name()).isEqualTo(CITY); assertThat(test.metaProperty(NUMBER).name()).isEqualTo(NUMBER); Map> map = test.metaPropertyMap(); assertThat(map).hasSize(NUM_PROPERTIES); assertThat(map).containsKey(STREET); assertThat(map).containsKey(CITY); assertThat(map).containsKey(NUMBER); assertThat(map).doesNotContainKey("NotHere"); assertThat(map.get(STREET)).isEqualTo(Address.meta().street()); } @Test void test_metaBean_invalidPropertyName() { MetaBean test = Address.meta(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.metaProperty("Rubbish")); } //----------------------------------------------------------------------- @Test void test_namedPropertyMethod() { Address address = new Address(); Property test = address.street(); assertThat((Object) test.bean()).isSameAs(address); assertThat(test.metaProperty()).isSameAs(Address.meta().street()); assertThat(test.get()).isNull(); address.setStreet("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_property_String() { Address address = new Address(); Property test = address.property(STREET); assertThat((Object) test.bean()).isSameAs(address); assertThat(test.metaProperty()).isSameAs(Address.meta().street()); assertThat(test.get()).isNull(); address.setStreet("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_namedMetaPropertyMethod() { Address address = new Address(); MetaProperty test = Address.meta().street(); assertThat(test.metaBean().beanType()).isEqualTo(Address.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isEqualTo(STREET); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(address)).isNull(); address.setStreet("A"); assertThat(test.get(address)).isEqualTo("A"); test.set(address, "B"); assertThat(test.get(address)).isEqualTo("B"); assertThat(test.put(address, "C")).isEqualTo("B"); assertThat(test.get(address)).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_metaProperty_String() { Address address = new Address(); MetaProperty test = Address.meta().metaProperty(STREET); assertThat(test.metaBean().beanType()).isEqualTo(Address.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isEqualTo(STREET); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(address)).isNull(); address.setStreet("A"); assertThat(test.get(address)).isEqualTo("A"); test.set(address, "B"); assertThat(test.get(address)).isEqualTo("B"); assertThat(test.put(address, "C")).isEqualTo("B"); assertThat(test.get(address)).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_metaProperty_types() { MetaProperty test = Address.meta().street(); assertThat(test.metaBean().beanType()).isEqualTo(Address.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.propertyGenericType()).isEqualTo(String.class); } @Test void test_metaProperty_annotations() { MetaProperty prop = Address.meta().street(); List test = prop.annotations(); assertThat(test.size()).isEqualTo(1); assertThat(test.get(0)).isInstanceOf(PropertyDefinition.class); } } ================================================ FILE: src/test/java/org/joda/beans/TestArray.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.SimpleName; import org.junit.jupiter.api.Test; /** * Test arrays using SimpleName. */ class TestArray { @Test void test_bean() { SimpleName person1 = new SimpleName(); person1.setForename("Etienne"); person1.setMiddleNames(new String[] {"Yakusa", "Mohito"}); person1.setSurname("Colebourne"); SimpleName person2 = new SimpleName(); person2.setForename("Etienne"); person2.setMiddleNames(new String[] {"Yakusa", "Mohito"}); person2.setSurname("Colebourne"); assertThat(person1).isEqualTo(person2); assertThat(person1.hashCode()).isEqualTo(person2.hashCode()); assertThat(person1).hasToString( "SimpleName{forename=Etienne, middleNames=[Yakusa, Mohito], surname=Colebourne}"); } } ================================================ FILE: src/test/java/org/joda/beans/TestBasicBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.impl.BasicBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.CompanyAddress; import org.joda.beans.sample.Person; import org.junit.jupiter.api.Test; /** * Test {@link BasicBean}. */ class TestBasicBean { @Test void test_equals() { Person a1 = new Person(); Person a2 = new Person(); Person b = new Person(); a1.setForename("Stephen"); a2.setForename("Stephen"); b.setForename("Etienne"); assertThat(a1.equals(a1)).isTrue(); assertThat(a1.equals(a2)).isTrue(); assertThat(a2.equals(a1)).isTrue(); assertThat(a2.equals(a2)).isTrue(); assertThat(a1.equals(b)).isFalse(); assertThat(b.equals(a1)).isFalse(); Object obj = "Weird type"; assertThat(b.equals(obj)).isFalse(); assertThat(b.equals(null)).isFalse(); } @Test void test_hashCode() { Person a1 = new Person(); Person a2 = new Person(); a1.setForename("Stephen"); a2.setForename("Stephen"); assertThat(a1.hashCode()).isEqualTo(a2.hashCode()); } @Test void test_toString() { Person a = new Person(); a.setForename("Stephen"); a.setSurname("Colebourne"); assertThat(a.toString()) .startsWith("Person{") .endsWith("}") .contains("forename=Stephen") .contains("surname=Colebourne"); } //----------------------------------------------------------------------- @Test void test_property_equals() { Address obj1 = new Address(); CompanyAddress obj2 = new CompanyAddress(); Property p1 = obj1.city(); Property p2 = obj2.city(); obj1.setCity("London"); obj2.setCity("London"); assertThat(p1).isEqualTo(p2); } @Test void test_property_hashCode() { Person obj1 = new Person(); Person obj2 = new Person(); Property p1 = obj1.forename(); Property p2 = obj2.forename(); obj1.setForename("Stephen"); obj2.setForename("Stephen"); assertThat(p1.hashCode()).isEqualTo(p2.hashCode()); } @Test void test_property_toString() { Person obj1 = new Person(); Property p1 = obj1.forename(); obj1.setForename("Stephen"); assertThat(p1).hasToString("Person:forename=Stephen"); } //----------------------------------------------------------------------- @Test void test_metaProperty_equals() { MetaProperty p1 = Address.meta().city(); MetaProperty p2 = CompanyAddress.meta().city(); assertThat(p1).isEqualTo(p2); } @Test void test_metaProperty_hashCode() { MetaProperty p1 = Person.meta().forename(); MetaProperty p2 = Person.meta().forename(); assertThat(p1.hashCode()).isEqualTo(p2.hashCode()); } @Test void test_metaProperty_toString() { MetaProperty mp1 = Person.meta().forename(); assertThat(mp1).hasToString("Person:forename"); } } ================================================ FILE: src/test/java/org/joda/beans/TestBeanCodeGenException.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import java.io.File; import org.joda.beans.gen.BeanCodeGenException; import org.junit.jupiter.api.Test; /** * Test {@link BeanCodeGenException}, message is parsed by plugins. */ class TestBeanCodeGenException { private static final File FILE = new File("."); @Test void testMessage() { BeanCodeGenException test = new BeanCodeGenException("rubbish", FILE, 123); assertThat(test.getMessage()).isEqualTo("Error in bean: " + FILE.toString() + ", Line: 123, Message: rubbish"); } } ================================================ FILE: src/test/java/org/joda/beans/TestBeanIterator.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import java.util.Iterator; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmEmpty; import org.joda.beans.sample.ImmTreeNode; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableList; /** * Test {@link BeanIterator}. */ class TestBeanIterator { @Test void test_iteration_noChildren() { ImmEmpty bean = ImmEmpty.builder().build(); Iterator it = JodaBeanUtils.beanIterator(bean); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(bean); assertThat(it.hasNext()).isFalse(); } @Test void test_iteration_nullChild() { Address bean = new Address(); Iterator it = JodaBeanUtils.beanIterator(bean); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(bean); assertThat(it.hasNext()).isFalse(); } @Test void test_iteration_childWithChildren() { ImmTreeNode node1 = ImmTreeNode.builder().name("1").build(); ImmTreeNode node2 = ImmTreeNode.builder().name("2").build(); ImmTreeNode root = ImmTreeNode.builder() .name("root") .child1(node1) .child2(node2) .build(); Iterator it = JodaBeanUtils.beanIterator(root); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(root); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node1); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node2); assertThat(it.hasNext()).isFalse(); } @Test void test_iteration_childWithChildrenOfChildren() { ImmTreeNode node1 = ImmTreeNode.builder().name("1").build(); ImmTreeNode node2 = ImmTreeNode.builder().name("2").build(); ImmTreeNode node3 = ImmTreeNode.builder() .name("3") .child1(node1) .child2(node2) .build(); ImmTreeNode root = ImmTreeNode.builder() .name("root") .child1(node3) .build(); Iterator it = JodaBeanUtils.beanIterator(root); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(root); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node3); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node1); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node2); assertThat(it.hasNext()).isFalse(); } @Test void test_iteration_childWithListOfChildren() { ImmTreeNode node1a = ImmTreeNode.builder().name("1a").build(); ImmTreeNode node1b = ImmTreeNode.builder().name("1b").build(); ImmTreeNode node1 = ImmTreeNode.builder() .name("1") .child1(node1a) .child2(node1b) .build(); ImmTreeNode node2a = ImmTreeNode.builder().name("2a").build(); ImmTreeNode node2b = ImmTreeNode.builder().name("2b").build(); ImmTreeNode node2 = ImmTreeNode.builder() .name("2") .child1(node2a) .child2(node2b) .build(); ImmTreeNode node3 = ImmTreeNode.builder().name("3").build(); ImmTreeNode root = ImmTreeNode.builder() .name("root") .child1(node3) .childList(ImmutableList.of(node1, node2)) .build(); Iterator it = JodaBeanUtils.beanIterator(root); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(root); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node3); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node1); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node1a); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node1b); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node2); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node2a); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(node2b); assertThat(it.hasNext()).isFalse(); } //----------------------------------------------------------------------- @Test void test_iteration_childWithNoChildren_FlexiBean() { FlexiBean bean1 = new FlexiBean(); Iterator it = JodaBeanUtils.beanIterator(bean1); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(bean1); assertThat(it.hasNext()).isFalse(); } @Test void test_iteration_childWithOneChild_FlexiBean() { FlexiBean bean1 = new FlexiBean(); FlexiBean bean2 = new FlexiBean(); bean1.set("a", bean2); Iterator it = JodaBeanUtils.beanIterator(bean1); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(bean1); assertThat(it.hasNext()).isTrue(); assertThat(it.next()).isSameAs(bean2); assertThat(it.hasNext()).isFalse(); } } ================================================ FILE: src/test/java/org/joda/beans/TestClone.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Date; import org.joda.beans.sample.Address; import org.joda.beans.sample.ClonePerson; import org.joda.beans.sample.Company; import org.joda.beans.sample.NoClone; import org.junit.jupiter.api.Test; /** * Test property using ClonePerson. */ class TestClone { @Test void test_bean() { ClonePerson base = new ClonePerson(); base.setSurname("Cable"); base.setMiddleNames(new String[] {"A", "B", "C"}); base.setFirstNames(Arrays.asList("Vince", "Matey")); base.setDateOfBirth(new Date()); Address address = new Address(); address.setCity("London"); base.setAddresses(Arrays.asList(address)); Company company = new Company(); company.setCompanyName("Government"); base.setCompanies(new Company[] {company}); base.setAmounts(new int[] {1, 2}); ClonePerson cloned = base.clone(); assertThat(cloned).isEqualTo(base); assertThat(cloned.getMiddleNames()).isNotSameAs(base.getMiddleNames()); assertThat(cloned.getFirstNames()).isNotSameAs(base.getFirstNames()); assertThat(cloned.getDateOfBirth()).isNotSameAs(base.getDateOfBirth()); assertThat(cloned.getAddresses()).isNotSameAs(base.getAddresses()); assertThat(cloned.getAddresses().get(0)).isNotSameAs(base.getAddresses().get(0)); assertThat(cloned.getCompanies()).isNotSameAs(base.getCompanies()); assertThat(cloned.getCompanies()[0]).isNotSameAs(base.getCompanies()[0]); assertThat(cloned.getAmounts()).isNotSameAs(base.getAmounts()); } @Test void test_noclone_on_mutable_bean_option() { // test that clone() was not code-generated Class c = NoClone.class; Method[] noCloneMethods = c.getDeclaredMethods(); for (Method method : noCloneMethods) { assertThat("clone").isNotEqualTo(method.getName()); } } } ================================================ FILE: src/test/java/org/joda/beans/TestCompanyAddress.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.sample.CompanyAddress; import org.junit.jupiter.api.Test; /** * Test property using Person. */ class TestCompanyAddress { private static final int NUM_PROPERTIES = 5; private static final String STREET = "street"; private static final String CITY = "city"; private static final String NUMBER = "number"; private static final String COMPANY_NAME = "companyName"; @Test void test_bean() { Bean test = CompanyAddress.meta().builder().build(); assertThat(test instanceof CompanyAddress).isTrue(); assertThat(test.metaBean()).isEqualTo(CompanyAddress.meta()); assertThat(test.propertyNames()).contains(STREET); assertThat(test.propertyNames()).contains(CITY); assertThat(test.propertyNames()).contains(NUMBER); assertThat(test.propertyNames()).contains(COMPANY_NAME); assertThat(test.propertyNames()).doesNotContain("Rubbish"); assertThat(test.property(STREET).name()).isEqualTo(STREET); assertThat(test.property(CITY).name()).isEqualTo(CITY); assertThat(test.property(NUMBER).name()).isEqualTo(NUMBER); assertThat(test.property(COMPANY_NAME).name()).isEqualTo(COMPANY_NAME); } @Test void test_bean_invalidPropertyName() { Bean test = CompanyAddress.meta().builder().build(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.property("Rubbish")); } //----------------------------------------------------------------------- @Test void test_metaBean() { MetaBean test = CompanyAddress.meta(); assertThat(test.beanType()).isEqualTo(CompanyAddress.class); assertThat(test.beanName()).isEqualTo(CompanyAddress.class.getName()); assertThat(test.metaPropertyCount()).isEqualTo(NUM_PROPERTIES); assertThat(test.metaPropertyExists(STREET)).isTrue(); assertThat(test.metaPropertyExists(CITY)).isTrue(); assertThat(test.metaPropertyExists(NUMBER)).isTrue(); assertThat(test.metaPropertyExists("Rubbish")).isFalse(); assertThat(test.metaProperty(STREET).name()).isEqualTo(STREET); assertThat(test.metaProperty(CITY).name()).isEqualTo(CITY); assertThat(test.metaProperty(NUMBER).name()).isEqualTo(NUMBER); Map> map = test.metaPropertyMap(); assertThat(map.size()).isEqualTo(NUM_PROPERTIES); assertThat(map.containsKey(STREET)).isTrue(); assertThat(map.containsKey(CITY)).isTrue(); assertThat(map.containsKey(NUMBER)).isTrue(); } @Test void test_metaBean_invalidPropertyName() { MetaBean test = CompanyAddress.meta(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.metaProperty("Rubbish")); } //----------------------------------------------------------------------- @Test void test_namedPropertyMethod_street() { CompanyAddress address = new CompanyAddress(); Property test = address.street(); assertThat((Object) test.bean()).isSameAs(address); assertThat(test.metaProperty()).isSameAs(CompanyAddress.meta().street()); assertThat(test.get()).isNull(); address.setStreet("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } @Test void test_namedPropertyMethod_companyName() { CompanyAddress address = new CompanyAddress(); Property test = address.companyName(); assertThat((Object) test.bean()).isSameAs(address); assertThat(test.metaProperty()).isSameAs(CompanyAddress.meta().companyName()); assertThat(test.get()).isNull(); address.setCompanyName("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_property_String_street() { CompanyAddress address = new CompanyAddress(); Property test = address.property(STREET); assertThat((Object) test.bean()).isSameAs(address); assertThat(test.metaProperty()).isSameAs(CompanyAddress.meta().street()); assertThat(test.get()).isNull(); address.setStreet("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } @Test void test_property_String_companyName() { CompanyAddress address = new CompanyAddress(); Property test = address.property(COMPANY_NAME); assertThat((Object) test.bean()).isSameAs(address); assertThat(test.metaProperty()).isSameAs(CompanyAddress.meta().companyName()); assertThat(test.get()).isNull(); address.setCompanyName("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_namedMetaPropertyMethod_street() { CompanyAddress address = new CompanyAddress(); MetaProperty test = CompanyAddress.meta().street(); assertThat(test.metaBean().beanType()).isEqualTo(CompanyAddress.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isEqualTo(STREET); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(address)).isNull(); address.setStreet("A"); assertThat(test.get(address)).isEqualTo("A"); test.set(address, "B"); assertThat(test.get(address)).isEqualTo("B"); assertThat(test.put(address, "C")).isEqualTo("B"); assertThat(test.get(address)).isEqualTo("C"); } @Test void test_namedMetaPropertyMethod_companyName() { CompanyAddress address = new CompanyAddress(); MetaProperty test = CompanyAddress.meta().companyName(); assertThat(test.metaBean().beanType()).isEqualTo(CompanyAddress.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isEqualTo(COMPANY_NAME); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(address)).isNull(); address.setCompanyName("A"); assertThat(test.get(address)).isEqualTo("A"); test.set(address, "B"); assertThat(test.get(address)).isEqualTo("B"); assertThat(test.put(address, "C")).isEqualTo("B"); assertThat(test.get(address)).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_metaProperty_String_street() { CompanyAddress address = new CompanyAddress(); MetaProperty test = CompanyAddress.meta().metaProperty(STREET); assertThat(test.metaBean().beanType()).isEqualTo(CompanyAddress.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isEqualTo(STREET); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(address)).isNull(); address.setStreet("A"); assertThat(test.get(address)).isEqualTo("A"); test.set(address, "B"); assertThat(test.get(address)).isEqualTo("B"); assertThat(test.put(address, "C")).isEqualTo("B"); assertThat(test.get(address)).isEqualTo("C"); } @Test void test_metaProperty_String_companyName() { CompanyAddress address = new CompanyAddress(); MetaProperty test = CompanyAddress.meta().metaProperty(COMPANY_NAME); assertThat(test.metaBean().beanType()).isEqualTo(CompanyAddress.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isEqualTo(COMPANY_NAME); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(address)).isNull(); address.setCompanyName("A"); assertThat(test.get(address)).isEqualTo("A"); test.set(address, "B"); assertThat(test.get(address)).isEqualTo("B"); assertThat(test.put(address, "C")).isEqualTo("B"); assertThat(test.get(address)).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_metaProperty_types() { MetaProperty test = CompanyAddress.meta().companyName(); assertThat(test.metaBean().beanType()).isEqualTo(CompanyAddress.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.propertyGenericType()).isEqualTo(String.class); } @Test void test_metaProperty_annotations() { MetaProperty prop = CompanyAddress.meta().companyName(); List test = prop.annotations(); assertThat(test).hasSize(1); assertThat(test.get(0)).isInstanceOf(PropertyDefinition.class); } } ================================================ FILE: src/test/java/org/joda/beans/TestFinalFieldBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.ArrayList; import java.util.List; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.FinalFieldBean; import org.joda.beans.sample.Person; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test FinalFieldBean. */ class TestFinalFieldBean { /** Bean. */ private FinalFieldBean bean; @BeforeEach void setUp() { bean = new FinalFieldBean("Hello"); bean.setFieldNonFinal("Hello"); bean.getListFinal().add("Hello"); bean.getFlexiFinal().append("Hello", "World"); bean.getPersonFinal().setSurname("Hello"); } //----------------------------------------------------------------------- @Test void test_finalString() { assertThat(bean.getFieldFinal()).isEqualTo("Hello"); assertThat(bean.fieldFinal().get()).isEqualTo("Hello"); assertThat(bean.fieldFinal().metaProperty().declaringType()).isEqualTo(FinalFieldBean.class); assertThat(bean.fieldFinal().metaProperty().getString(bean)).isEqualTo("Hello"); assertThat(bean.fieldFinal().metaProperty().get(bean)).isEqualTo("Hello"); assertThat(bean.fieldFinal().metaProperty().name()).isEqualTo("fieldFinal"); assertThat(bean.fieldFinal().metaProperty().style()).isEqualTo(PropertyStyle.READ_ONLY); assertThat(bean.fieldFinal().metaProperty().propertyType()).isEqualTo(String.class); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> bean.fieldFinal().set("foo")); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> bean.fieldFinal().metaProperty().set(bean, "foo")); } //----------------------------------------------------------------------- @Test void test_nonFinalString() { assertThat(bean.getFieldNonFinal()).isEqualTo("Hello"); assertThat(bean.fieldNonFinal().get()).isEqualTo("Hello"); assertThat(bean.fieldNonFinal().metaProperty().declaringType()).isEqualTo(FinalFieldBean.class); assertThat(bean.fieldNonFinal().metaProperty().getString(bean)).isEqualTo("Hello"); assertThat(bean.fieldNonFinal().metaProperty().get(bean)).isEqualTo("Hello"); assertThat(bean.fieldNonFinal().metaProperty().name()).isEqualTo("fieldNonFinal"); assertThat(bean.fieldNonFinal().metaProperty().style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(bean.fieldNonFinal().metaProperty().propertyType()).isEqualTo(String.class); bean.fieldNonFinal().set("foo"); assertThat(bean.getFieldNonFinal()).isEqualTo("foo"); bean.fieldNonFinal().metaProperty().set(bean, "bar"); assertThat(bean.getFieldNonFinal()).isEqualTo("bar"); } //----------------------------------------------------------------------- @Test void test_finalList() { List list = new ArrayList<>(); list.add("Hello"); assertThat(bean.getListFinal()).isEqualTo(list); assertThat(bean.listFinal().get()).isEqualTo(list); assertThat(bean.listFinal().metaProperty().declaringType()).isEqualTo(FinalFieldBean.class); assertThat(bean.listFinal().metaProperty().get(bean)).isEqualTo(list); assertThat(bean.listFinal().metaProperty().name()).isEqualTo("listFinal"); assertThat(bean.listFinal().metaProperty().style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(bean.listFinal().metaProperty().propertyType()).isEqualTo(List.class); list.add("foo"); List expected1 = new ArrayList<>(list); bean.listFinal().set(list); assertThat(bean.getListFinal()).isEqualTo(expected1); list.add("bar"); List expected2 = new ArrayList<>(list); bean.listFinal().metaProperty().set(bean, list); assertThat(bean.getListFinal()).isEqualTo(expected2); } //----------------------------------------------------------------------- @Test void test_finalBean() { FlexiBean flexi = new FlexiBean(); flexi.append("Hello", "World"); assertThat(bean.getFlexiFinal()).isEqualTo(flexi); assertThat(bean.flexiFinal().get()).isEqualTo(flexi); assertThat(bean.flexiFinal().metaProperty().declaringType()).isEqualTo(FinalFieldBean.class); assertThat(bean.flexiFinal().metaProperty().get(bean)).isEqualTo(flexi); assertThat(bean.flexiFinal().metaProperty().name()).isEqualTo("flexiFinal"); assertThat(bean.flexiFinal().metaProperty().style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(bean.flexiFinal().metaProperty().propertyType()).isEqualTo(FlexiBean.class); flexi.append("foo", "foos"); FlexiBean expected1 = new FlexiBean(flexi); bean.flexiFinal().set(flexi); assertThat(bean.getFlexiFinal()).isEqualTo(expected1); flexi.append("bar", "bars"); FlexiBean expected2 = new FlexiBean(flexi); bean.flexiFinal().metaProperty().set(bean, flexi); assertThat(bean.getFlexiFinal()).isEqualTo(expected2); } //----------------------------------------------------------------------- @Test void test_finalPerson() { Person person = new Person(); person.setSurname("Hello"); assertThat(bean.getPersonFinal()).isEqualTo(person); assertThat(bean.personFinal().get()).isEqualTo(person); assertThat(bean.personFinal().metaProperty().declaringType()).isEqualTo(FinalFieldBean.class); assertThat(bean.personFinal().metaProperty().get(bean)).isEqualTo(person); assertThat(bean.personFinal().metaProperty().name()).isEqualTo("personFinal"); assertThat(bean.personFinal().metaProperty().style()).isEqualTo(PropertyStyle.READ_ONLY); assertThat(bean.personFinal().metaProperty().propertyType()).isEqualTo(Person.class); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> bean.personFinal().set(new Person())); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> bean.personFinal().metaProperty().set(bean, new Person())); } } ================================================ FILE: src/test/java/org/joda/beans/TestFlexiBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.offset; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; import java.util.Map; import org.joda.beans.impl.flexi.FlexiBean; import org.junit.jupiter.api.Test; /** * Test {@link FlexiBean}. */ class TestFlexiBean { @Test void test_constructor() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); } @Test void test_constructor_copy() { FlexiBean base = new FlexiBean(); base.set("a", "x"); base.set("b", "y"); FlexiBean test = new FlexiBean(base); assertThat(test).isNotSameAs(base); assertThat(test).isEqualTo(base); } //----------------------------------------------------------------------- @Test void test_serialization() throws Exception { FlexiBean test = new FlexiBean(); test.put("name", "Etienne"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(test); } try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) { try (ObjectInputStream ois = new ObjectInputStream(bais)) { Object obj = ois.readObject(); assertThat(test).isEqualTo(obj); } } } //------------------------------------------------------------------------- @Test void test_clone() { FlexiBean base = new FlexiBean(); base.set("a", "x"); base.set("b", "y"); FlexiBean test = base.clone(); assertThat(test).isNotSameAs(base); assertThat(test).isEqualTo(base); } @Test void test_equalsHashCode() { FlexiBean a1 = new FlexiBean(); FlexiBean a2 = new FlexiBean(); FlexiBean b = new FlexiBean(); a1.set("first", "A"); a2.set("first", "A"); b.set("first", "B"); assertThat(a1.equals(a1)).isTrue(); assertThat(a1.equals(a2)).isTrue(); assertThat(a2.equals(a1)).isTrue(); assertThat(a2.equals(a2)).isTrue(); assertThat(a1.hashCode()).isEqualTo(a2.hashCode()); assertThat(a1.equals(b)).isFalse(); assertThat(b.equals(a1)).isFalse(); Object obj = "Weird type"; assertThat(b.equals(obj)).isFalse(); assertThat(b.equals(null)).isFalse(); } @Test void test_toString() { FlexiBean test = new FlexiBean(); test.set("a", "b"); assertThat(test.toString()).isEqualTo("FlexiBean{a=b}"); } //------------------------------------------------------------------------- @Test void test_basics() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); assertThat(test.contains("a")).isFalse(); assertThat(test.contains("b")).isFalse(); assertThat(test.get("a")).isNull(); assertThat(test.get("b")).isNull(); test.set("a", "x"); assertThat(test.size()).isEqualTo(1); assertThat(test.contains("a")).isTrue(); assertThat(test.contains("b")).isFalse(); assertThat(test.get("a")).isEqualTo("x"); assertThat(test.get("b")).isNull(); test.set("b", "y"); assertThat(test.size()).isEqualTo(2); assertThat(test.contains("a")).isTrue(); assertThat(test.contains("b")).isTrue(); assertThat(test.get("a")).isEqualTo("x"); assertThat(test.get("b")).isEqualTo("y"); test.set("b", "z"); assertThat(test.size()).isEqualTo(2); assertThat(test.contains("a")).isTrue(); assertThat(test.contains("b")).isTrue(); assertThat(test.get("a")).isEqualTo("x"); assertThat(test.get("b")).isEqualTo("z"); test.remove("b"); assertThat(test.size()).isEqualTo(1); assertThat(test.contains("a")).isTrue(); assertThat(test.contains("b")).isFalse(); assertThat(test.get("a")).isEqualTo("x"); assertThat(test.get("b")).isNull(); } @Test void test_type_string() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); test.set("a", "x"); assertThat(test.get("a")).isEqualTo("x"); assertThat(test.get("a", String.class)).isEqualTo("x"); assertThat(test.getString("a")).isEqualTo("x"); assertThat(test.getString("b")).isNull(); } @Test void test_type_long() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); test.set("a", Long.valueOf(2)); assertThat(test.get("a")).isEqualTo(Long.valueOf(2)); assertThat(test.get("a", Long.class)).isEqualTo(Long.valueOf(2)); assertThat(test.getLong("a")).isEqualTo(2L); assertThat(test.getLong("a", 1L)).isEqualTo(2); assertThat(test.getLong("b", 1L)).isEqualTo(1); } @Test void test_type_int() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); test.set("a", Integer.valueOf(2)); assertThat(test.get("a")).isEqualTo(Integer.valueOf(2)); assertThat(test.get("a", Integer.class)).isEqualTo(Integer.valueOf(2)); assertThat(test.getInt("a")).isEqualTo(2); assertThat(test.getInt("a", 1)).isEqualTo(2); assertThat(test.getInt("b", 1)).isEqualTo(1); } @Test void test_type_double() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); test.set("a", Double.valueOf(1.2d)); assertThat(test.get("a")).isEqualTo(Double.valueOf(1.2d)); assertThat(test.get("a", Double.class)).isEqualTo(Double.valueOf(1.2d)); assertThat(test.getDouble("a")).isEqualTo(1.2d); assertThat(test.getDouble("a", 0.5d)).isEqualTo(1.2d); assertThat(test.getDouble("b", 0.5d)).isEqualTo(0.5d, offset(0.0001d)); } @Test void test_type_boolean() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); test.set("a", Boolean.TRUE); assertThat(test.get("a")).isEqualTo(Boolean.TRUE); assertThat(test.get("a", Boolean.class)).isEqualTo(Boolean.TRUE); assertThat(test.getBoolean("a")).isTrue(); } //------------------------------------------------------------------------- @Test void test_propertyDefine_propertyRemove() { FlexiBean flexi = new FlexiBean(); assertThat(flexi.propertyNames().size()).isEqualTo(0); flexi.propertyDefine("name", String.class); assertThat(flexi.propertyNames().size()).isEqualTo(1); Property prop = flexi.property("name"); assertThat(prop.name()).isEqualTo("name"); assertThat(prop.get()).isNull(); flexi.propertyRemove("name"); assertThat(flexi.propertyNames().size()).isEqualTo(0); } @Test void test_metaBean() { FlexiBean flexi = new FlexiBean(); DynamicMetaBean meta = flexi.metaBean(); assertThat(meta.metaPropertyCount()).isEqualTo(0); meta.metaPropertyDefine("name", String.class); assertThat(meta.metaPropertyCount()).isEqualTo(1); MetaProperty prop = meta.metaProperty("name"); assertThat(prop.name()).isEqualTo("name"); assertThat(prop.get(flexi)).isNull(); meta.metaPropertyDefine("name", String.class); assertThat(meta.metaPropertyCount()).isEqualTo(1); MetaProperty prop2 = meta.metaProperty("address"); assertThat(prop2).isNotNull(); assertThat(meta.metaPropertyCount()).isEqualTo(1); // meta-property object created but data not changed } //----------------------------------------------------------------------- @Test void test_putAll() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); Map map = new HashMap<>(); test.putAll(map); assertThat(test.size()).isEqualTo(0); map.put("a", "x"); map.put("b", "y"); test.putAll(map); assertThat(test.size()).isEqualTo(2); assertThat(test.contains("a")).isTrue(); assertThat(test.contains("b")).isTrue(); map.clear(); map.put("c", "z"); test.putAll(map); assertThat(test.size()).isEqualTo(3); assertThat(test.contains("a")).isTrue(); assertThat(test.contains("b")).isTrue(); assertThat(test.contains("c")).isTrue(); } @Test void test_remove() { FlexiBean test = new FlexiBean(); assertThat(test.size()).isEqualTo(0); test.remove("a"); assertThat(test.size()).isEqualTo(0); test.put("a", "x"); test.remove("a"); assertThat(test.size()).isEqualTo(0); } @Test void test_toMap() { FlexiBean base = new FlexiBean(); Map test = base.toMap(); assertThat(test.size()).isEqualTo(0); base.put("a", "x"); base.put("b", "y"); test = base.toMap(); assertThat(test.size()).isEqualTo(2); assertThat(test.containsKey("a")).isTrue(); assertThat(test.containsKey("b")).isTrue(); } //------------------------------------------------------------------------- @Test void test_invalidProperty() { FlexiBean flexi = new FlexiBean(); assertThatIllegalArgumentException() .isThrownBy(() -> flexi.propertyDefine("bad-name", String.class)); } @Test void test_append_invalidProperty() { FlexiBean flexi = new FlexiBean(); assertThatIllegalArgumentException() .isThrownBy(() -> flexi.append("bad-name", "a")); } @Test void test_set_invalidProperty() { FlexiBean flexi = new FlexiBean(); assertThatIllegalArgumentException() .isThrownBy(() -> flexi.set("bad-name", "a")); } @Test void test_put_invalidProperty() { FlexiBean flexi = new FlexiBean(); assertThatIllegalArgumentException() .isThrownBy(() -> flexi.put("bad-name", "a")); } @Test void test_putAll_invalidKey() { FlexiBean test = new FlexiBean(); Map map = new HashMap<>(); map.put("1", "x"); assertThatIllegalArgumentException() .isThrownBy(() -> test.putAll(map)); } } ================================================ FILE: src/test/java/org/joda/beans/TestImmutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.NoSuchElementException; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmAddress.Builder; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.ImmPersonNonFinal; import org.joda.beans.sample.ImmSubPersonNonFinal; import org.joda.beans.sample.ImmSubSubPersonFinal; import org.joda.beans.sample.SimpleAnnotation; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultiset; /** * Test property using Person. */ class TestImmutable { @Test void test_bean() { ImmAddress address = ImmAddress.builder() .number(12) .street("Park Lane") .city("Smallville") .owner(ImmPerson.builder().forename("John").surname("Doggett").build()) .build(); assertThat(address.getCity()).isEqualTo("Smallville"); assertThat(address.getStreet()).isEqualTo("Park Lane"); } @Test void test_builder() { Builder builder = ImmAddress.builder() .set("number", 12) .set("street", "Park Lane"); assertThat(builder.get("number")).isEqualTo(12); assertThat(builder.get("street")).isEqualTo("Park Lane"); assertThat(builder.get("city")).isNull(); builder.set("city", "Smallville") .set("owner", ImmPerson.builder().forename("John").surname("Doggett").build()); assertThat(builder.get("number")).isEqualTo(12); assertThat(builder.get("street")).isEqualTo("Park Lane"); assertThat(builder.get("city")).isEqualTo("Smallville"); ImmAddress address = builder.build(); assertThat(address.getCity()).isEqualTo("Smallville"); assertThat(address.getStreet()).isEqualTo("Park Lane"); } @Test void test_with() { ImmAddress address = ImmAddress.builder() .set("number", 12) .set("street", "Park Lane") .set("city", "Smallville") .set("owner", ImmPerson.builder().forename("John").surname("Doggett").build()) .build(); address = address.toBuilder().street("Park Road").build(); assertThat(address.getCity()).isEqualTo("Smallville"); assertThat(address.getStreet()).isEqualTo("Park Road"); } @Test void test_annotations() { ImmPerson person = ImmPerson.builder().forename("John").surname("Doggett").build(); assertThat(person.metaBean().numberOfCars().annotationOpt(SimpleAnnotation.class)) .isPresent() .hasValueSatisfying(anno -> { assertThat(anno.second()).isEqualTo("2"); }); assertThat(person.metaBean().age() .annotationOpt(SimpleAnnotation.class)) .isPresent() .hasValueSatisfying(anno -> { assertThat(anno.first()).isEqualTo("1"); }); } //----------------------------------------------------------------------- @Test void test_builder_getInvalidPropertyName() { BeanBuilder builder = ImmAddress.meta().builder(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.get("Rubbish")); } @Test void test_builder_setInvalidPropertyName() { BeanBuilder builder = ImmAddress.meta().builder(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.set("Rubbish", "")); } //----------------------------------------------------------------------- @Test void test_builder_subclass() { ImmSubSubPersonFinal.Builder builder = ImmSubSubPersonFinal.meta().builder(); builder.set(ImmPersonNonFinal.meta().forename(), "Bobby"); builder.set(ImmSubPersonNonFinal.meta().middleName(), "Joe"); builder.set(ImmSubSubPersonFinal.meta().codeCounts(), ImmutableMultiset.of()); assertThat(builder.get("forename")).isEqualTo("Bobby"); assertThat(builder.get("middleName")).isEqualTo("Joe"); assertThat(builder.get("codeCounts")).isEqualTo(ImmutableMultiset.of()); assertThat(builder.get(ImmPersonNonFinal.meta().forename())).isEqualTo("Bobby"); assertThat(builder.get(ImmSubPersonNonFinal.meta().middleName())).isEqualTo("Joe"); assertThat(builder.get(ImmSubSubPersonFinal.meta().codeCounts())).isEqualTo(ImmutableMultiset.of()); ImmSubSubPersonFinal result = builder.build(); assertThat(result.getForename()).isEqualTo("Bobby"); assertThat(result.getMiddleName()).isEqualTo("Joe"); assertThat(result.getCodeCounts()).isEmpty(); } @Test void test_builder_subclass_getInvalidPropertyName() { ImmSubSubPersonFinal.Builder builder = ImmSubSubPersonFinal.meta().builder(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.get("Rubbish")); } @Test void test_builder_subclass_setInvalidPropertyName() { ImmSubSubPersonFinal.Builder builder = ImmSubSubPersonFinal.meta().builder(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.set("Rubbish", "")); } //----------------------------------------------------------------------- @Test void test_builder_defaultValue() { ImmPerson person = ImmPerson.builder() .forename("A") .surname("B") .build(); assertThat(person.getForename()).isEqualTo("A"); assertThat(person.getSurname()).isEqualTo("B"); assertThat(person.getNumberOfCars()).isEqualTo(1); } //----------------------------------------------------------------------- @Test void test_builder_methodTypes() { Calendar cal = Calendar.getInstance(); GregorianCalendar gcal = new GregorianCalendar(2015, 5, 30); ImmutableList listCal = ImmutableList.of(cal); ImmutableList listGcal = ImmutableList.of(gcal); ImmutableList listNumbers = ImmutableList.of(2d, 5, 3f); ImmutableList listInts = ImmutableList.of(1, 2, 3); ImmGuava obj = ImmGuava.builder() .list(cal, gcal) .list(listCal) .listWildExtendsT(listCal) .listWildExtendsT(listGcal) .listWildExtendsNumber(2d, 5, 3f) .listWildExtendsNumber(listNumbers) .listWildExtendsNumber(listInts) .listWildExtendsComparable(2d, 5, 3f) .listWildExtendsComparable(listInts) .build(); assertThat(obj.getList()).isEqualTo(listCal); } } ================================================ FILE: src/test/java/org/joda/beans/TestJodaBeanUtils.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatNullPointerException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.Pair; import org.joda.beans.sample.Person; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; /** * Test {@link JodaBeanUtils}. */ class TestJodaBeanUtils { //----------------------------------------------------------------------- @Test void test_notNull_ok() { JodaBeanUtils.notNull("", "name"); } @Test void test_notNull_notOk() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notNull(null, "name")); } //----------------------------------------------------------------------- @Test void test_notBlank_String_ok() { JodaBeanUtils.notBlank("Blah", "name"); } @Test void test_notBlank_String_notOk_empty() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notBlank("", "name")); } @Test void test_notBlank_String_notOk_allWhitespace() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notBlank(" ", "name")); } @Test void test_notBlank_String_notOk_null() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notBlank((String) null, "name")); } //----------------------------------------------------------------------- @Test void test_notEmpty_String_ok() { JodaBeanUtils.notEmpty("Blah", "name"); } @Test void test_notEmpty_String_notOk_empty() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notBlank("", "name")); } @Test void test_notEmpty_String_notOk_null() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notEmpty((String) null, "name")); } //----------------------------------------------------------------------- @Test void test_notEmpty_Collection_ok() { JodaBeanUtils.notEmpty(Arrays.asList("Blah"), "name"); } @Test void test_notEmpty_Collection_notOk_empty() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notEmpty(new ArrayList(), "name")); } @Test void test_notEmpty_Collection_notOk_null() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notEmpty((Collection) null, "name")); } //----------------------------------------------------------------------- @Test void test_notEmpty_Map_ok() { Map map = new HashMap<>(); map.put("A", "B"); JodaBeanUtils.notEmpty(map, "name"); } @Test void test_notEmpty_Map_notOk_empty() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notEmpty(new HashMap(), "name")); } @Test void test_notEmpty_Map_notOk_null() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.notEmpty((Map) null, "name")); } //----------------------------------------------------------------------- @Test void test_propertiesEqual_propertiesHashCode() { Pair a = new Pair(); a.setFirst("A"); FlexiBean b = new FlexiBean(); b.set("first", "A"); assertThat(JodaBeanUtils.propertiesEqual(a, b)).isFalse(); assertThat(JodaBeanUtils.propertiesEqual(b, a)).isFalse(); b.set("second", null); assertThat(JodaBeanUtils.propertiesEqual(a, b)).isTrue(); assertThat(JodaBeanUtils.propertiesEqual(b, a)).isTrue(); assertThat(JodaBeanUtils.propertiesHashCode(a)).isEqualTo(JodaBeanUtils.propertiesHashCode(b)); b.set("second", "B"); assertThat(JodaBeanUtils.propertiesEqual(a, b)).isFalse(); assertThat(JodaBeanUtils.propertiesEqual(b, a)).isFalse(); a.setSecond("B"); assertThat(JodaBeanUtils.propertiesEqual(a, b)).isTrue(); assertThat(JodaBeanUtils.propertiesEqual(b, a)).isTrue(); assertThat(JodaBeanUtils.propertiesHashCode(a)).isEqualTo(JodaBeanUtils.propertiesHashCode(b)); } //------------------------------------------------------------------------- @Test void test_equal() { assertThat(JodaBeanUtils.equal("A", "AA".substring(0, 1))).isTrue(); assertThat(JodaBeanUtils.equal("A", "B")).isFalse(); assertThat(JodaBeanUtils.equal("A", null)).isFalse(); assertThat(JodaBeanUtils.equal(null, "A")).isFalse(); } @Test void test_equal_ObjectArray() { Object[] a1 = new Object[] {1, 2, 3}; Object[] a2 = new Object[] {1, 2, 3}; Object[] b = new Object[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_IntegerArray() { Object[] a1 = new Integer[] {1, 2, 3}; Object[] a2 = new Integer[] {1, 2, 3}; Object[] b = new Integer[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_IntegerNumberArray() { Object[] a = new Integer[] {1, 2, 3}; Object[] b = new Number[] {1, 2, 3}; assertThat(JodaBeanUtils.equal(a, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a)).isFalse(); } @Test void test_equal_IntegerIntArray() { Object[] a = new Integer[] {1, 2, 3}; int[] b = new int[] {1, 2, 3}; assertThat(JodaBeanUtils.equal(a, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a)).isFalse(); } @Test void test_equal_IntArray() { int[] a1 = new int[] {1, 2, 3}; int[] a2 = new int[] {1, 2, 3}; int[] b = new int[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_MixedArrays() { byte[] b = new byte[] {1, 2, 3}; short[] s = new short[] {1, 2, 3}; int[] i = new int[] {1, 2, 3}; long[] l = new long[] {1, 2, 4}; boolean[] bl = new boolean[] {true, false, true}; char[] c = new char[] {'1', '2', '3'}; float[] f = new float[] {1f, 2f, 3f}; double[] d = new double[] {1d, 2d, 3d}; assertThat(JodaBeanUtils.equal(b, i)).isFalse(); assertThat(JodaBeanUtils.equal(s, i)).isFalse(); assertThat(JodaBeanUtils.equal(i, l)).isFalse(); assertThat(JodaBeanUtils.equal(l, i)).isFalse(); assertThat(JodaBeanUtils.equal(bl, i)).isFalse(); assertThat(JodaBeanUtils.equal(c, i)).isFalse(); assertThat(JodaBeanUtils.equal(f, i)).isFalse(); assertThat(JodaBeanUtils.equal(d, i)).isFalse(); } @Test void test_equal_LongArray() { long[] a1 = new long[] {1, 2, 3}; long[] a2 = new long[] {1, 2, 3}; long[] b = new long[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_DoubleArray() { double[] a1 = new double[] {1, 2, 3}; double[] a2 = new double[] {1, 2, 3}; double[] b = new double[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_FloatArray() { float[] a1 = new float[] {1, 2, 3}; float[] a2 = new float[] {1, 2, 3}; float[] b = new float[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_ShortArray() { short[] a1 = new short[] {1, 2, 3}; short[] a2 = new short[] {1, 2, 3}; short[] b = new short[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_CharArray() { char[] a1 = new char[] {1, 2, 3}; char[] a2 = new char[] {1, 2, 3}; char[] b = new char[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_ByteArray() { byte[] a1 = new byte[] {1, 2, 3}; byte[] a2 = new byte[] {1, 2, 3}; byte[] b = new byte[] {1, 2, 4}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } @Test void test_equal_BooleanArray() { boolean[] a1 = new boolean[] {true, false}; boolean[] a2 = new boolean[] {true, false}; boolean[] b = new boolean[] {true, true}; assertThat(JodaBeanUtils.equal(a1, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, a2)).isTrue(); assertThat(JodaBeanUtils.equal(a2, a1)).isTrue(); assertThat(JodaBeanUtils.equal(a1, b)).isFalse(); assertThat(JodaBeanUtils.equal(b, a1)).isFalse(); } //----------------------------------------------------------------------- @Test void test_equal_floats() { assertThat(JodaBeanUtils.equal(1.01f, 1.01f)).isTrue(); assertThat(JodaBeanUtils.equal(1.0f, 1.2f)).isFalse(); } @Test void test_equalWithTolerance_floats_zeroTolerance() { double tolerance = 0d; assertThat(JodaBeanUtils.equalWithTolerance(1.01f, 1.01f, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1f, 1.2f, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NaN, Float.NaN, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NaN, 1f, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(1f, Float.NaN, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, tolerance)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Float.POSITIVE_INFINITY, Float.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.MAX_VALUE, Float.POSITIVE_INFINITY, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, tolerance)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, tolerance)) .isFalse(); } @Test void test_equalWithTolerance_floats_someTolerance() { double tolerance = 0.125d; assertThat(JodaBeanUtils.equalWithTolerance(1f, 1.250001f, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(1f, 1.125f, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1f, 1.124999f, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1f, 0.875001f, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1f, 0.875f, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1f, 0.874999f, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NaN, Float.NaN, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NaN, 1f, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(1f, Float.NaN, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, tolerance)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Float.POSITIVE_INFINITY, Float.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.MAX_VALUE, Float.POSITIVE_INFINITY, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 0d)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, tolerance)) .isFalse(); } //----------------------------------------------------------------------- @Test void test_equal_doubles() { assertThat(JodaBeanUtils.equal(1.01d, 1.01d)).isTrue(); assertThat(JodaBeanUtils.equal(1.0d, 1.2d)).isFalse(); assertThat(JodaBeanUtils.equal(Double.NaN, Double.NaN)).isTrue(); assertThat(JodaBeanUtils.equal(Double.NaN, 1d)).isFalse(); assertThat(JodaBeanUtils.equal(1d, Double.NaN)).isFalse(); assertThat(JodaBeanUtils.equal(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)).isTrue(); assertThat(JodaBeanUtils.equal(Double.POSITIVE_INFINITY, Double.MAX_VALUE)).isFalse(); assertThat(JodaBeanUtils.equal(Double.MAX_VALUE, Double.POSITIVE_INFINITY)).isFalse(); assertThat(JodaBeanUtils.equal(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY)).isTrue(); assertThat(JodaBeanUtils.equal(Double.NEGATIVE_INFINITY, -Double.MAX_VALUE)).isFalse(); assertThat(JodaBeanUtils.equal(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY)).isFalse(); } @Test void test_equalWithTolerance_doubles_zeroTolerance() { double tolerance = 0d; assertThat(JodaBeanUtils.equalWithTolerance(1.01d, 1.01d, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1d, 1.2d, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NaN, Double.NaN, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NaN, 1d, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(1d, Double.NaN, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, tolerance)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Double.POSITIVE_INFINITY, Double.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.MAX_VALUE, Double.POSITIVE_INFINITY, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, tolerance)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, tolerance)) .isFalse(); } @Test void test_equalWithTolerance_doubles_someTolerance() { double tolerance = 0.125d; assertThat(JodaBeanUtils.equalWithTolerance(1d, 1.250001d, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(1d, 1.125d, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1d, 1.124999d, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1d, 0.875001d, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1d, 0.875d, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(1d, 0.874999d, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NaN, Double.NaN, tolerance)).isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NaN, 1d, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(1d, Double.NaN, tolerance)).isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, tolerance)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Double.POSITIVE_INFINITY, Double.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.MAX_VALUE, Double.POSITIVE_INFINITY, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 0d)) .isTrue(); assertThat(JodaBeanUtils.equalWithTolerance(Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, tolerance)) .isFalse(); assertThat(JodaBeanUtils.equalWithTolerance(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, tolerance)) .isFalse(); } //----------------------------------------------------------------------- @Test void test_hashCode_Object() { assertThat(JodaBeanUtils.hashCode("A")).isEqualTo("A".hashCode()); assertThat(JodaBeanUtils.hashCode(null)).isEqualTo(0); assertThat(JodaBeanUtils.hashCode(new byte[] { 1 })).isEqualTo(Arrays.hashCode(new byte[] { 1 })); assertThat(JodaBeanUtils.hashCode(new short[] { 1 })).isEqualTo(Arrays.hashCode(new short[] { 1 })); assertThat(JodaBeanUtils.hashCode(new int[] { 1 })).isEqualTo(Arrays.hashCode(new int[] { 1 })); assertThat(JodaBeanUtils.hashCode(new long[] { 1 })).isEqualTo(Arrays.hashCode(new long[] { 1 })); assertThat(JodaBeanUtils.hashCode(new boolean[] { true })).isEqualTo(Arrays.hashCode(new boolean[] { true })); assertThat(JodaBeanUtils.hashCode(new char[] { '1' })).isEqualTo(Arrays.hashCode(new char[] { '1' })); assertThat(JodaBeanUtils.hashCode(new float[] { 1f })).isEqualTo(Arrays.hashCode(new float[] { 1f })); assertThat(JodaBeanUtils.hashCode(new double[] { 1d })).isEqualTo(Arrays.hashCode(new double[] { 1d })); } //----------------------------------------------------------------------- @Test void test_copy() { Person p = new Person(); p.setForename("Stephen"); p.setSurname("Colebourne"); p.setExtensions(new FlexiBean()); p.getExtensions().set("Foo", "bar"); ImmPerson copied = JodaBeanUtils.copy(p, ImmPerson.class).build(); assertThat(copied).isNotSameAs(p); assertThat(copied.getForename()).isEqualTo(p.getForename()); assertThat(copied.getSurname()).isEqualTo(p.getSurname()); } @Test void test_copyInto() { Person p = new Person(); p.setForename("Stephen"); p.setExtensions(new FlexiBean()); p.getExtensions().set("Foo", "bar"); ImmPerson copied = JodaBeanUtils.copyInto(p, ImmPerson.meta(), ImmPerson.builder()).build(); assertThat(copied).isNotSameAs(p); assertThat(copied.getForename()).isEqualTo(p.getForename()); assertThat(copied.getSurname()).isNull(); } //----------------------------------------------------------------------- @Test void test_cloneArray_primitive1d() { int[] array = {1, 2, 3}; int[] cloned = (int[]) JodaBeanUtils.cloneArray(array); assertThat(cloned) .isNotSameAs(array) .isEqualTo(array); array[0] = 99; assertThat(cloned).isNotEqualTo(array); } @Test void test_cloneArray_primitive2d() { int[][] array = {{1, 2, 3}, {4}, {}}; int[][] cloned = (int[][]) JodaBeanUtils.cloneArray(array); assertThat(cloned) .isNotSameAs(array) .isEqualTo(array); array[2] = new int[] {99}; assertThat(cloned).isNotEqualTo(array); } @Test void test_cloneArray_string2d() { String[][] array = {{"1", "2", "3"}, {"4"}, {}}; String[][] cloned = (String[][]) JodaBeanUtils.cloneArray(array); assertThat(cloned) .isNotSameAs(array) .isEqualTo(array); array[2] = new String[] {"99"}; assertThat(cloned).isNotEqualTo(array); } @Test void test_clone() { Person p = new Person(); p.setForename("Stephen"); p.setSurname("Colebourne"); p.getOtherAddressMap().put("A", new Address()); p.getOtherAddressMap().get("A").setCity("London"); Person cloned = JodaBeanUtils.clone(p); assertThat(cloned).isNotSameAs(p); assertThat(cloned).isEqualTo(p); p.getOtherAddressMap().put("B", new Address()); assertThat(cloned).isNotEqualTo(p); } //----------------------------------------------------------------------- @Test void test_listType_Person_addressList() { MetaProperty> test = Person.meta().addressList(); assertThat(JodaBeanUtils.collectionType(test, Person.class)).isEqualTo(Address.class); } @Test void test_listType_Person_addressesList() { MetaProperty>> test = Person.meta().addressesList(); assertThat(JodaBeanUtils.collectionType(test, Person.class)).isEqualTo(List.class); } @Test void test_multisetType_Person_otherAddressMap() { MetaProperty> test = ImmPerson.meta().codeCounts(); assertThat(JodaBeanUtils.collectionType(test, Person.class)).isEqualTo(String.class); } @Test void test_integerType_Person_collectionTypeInvalid() { MetaProperty test = ImmPerson.meta().age(); assertThat(JodaBeanUtils.collectionType(test, Person.class)).isNull(); } //------------------------------------------------------------------------- @Test void test_collectionTypeTypes_valid() { MetaProperty>> test = Person.meta().addressesList(); List> expected = ImmutableList.>of(Address.class); assertThat(JodaBeanUtils.collectionTypeTypes(test, Person.class)).isEqualTo(expected); } @Test void test_collectionTypeTypes_invalidNoGenerics() { MetaProperty> test = Person.meta().addressList(); List> expected = Collections.emptyList(); assertThat(JodaBeanUtils.collectionTypeTypes(test, Person.class)).isEqualTo(expected); } @Test void test_collectionTypeTypes_invalidNotCollection() { MetaProperty>> test = ImmAddress.meta().listNumericInMap(); List> expected = Collections.emptyList(); assertThat(JodaBeanUtils.collectionTypeTypes(test, ImmAddress.class)).isEqualTo(expected); } //------------------------------------------------------------------------- @Test void test_mapType_Person_otherAddressMap() { MetaProperty> test = Person.meta().otherAddressMap(); assertThat(JodaBeanUtils.mapKeyType(test, Person.class)).isEqualTo(String.class); assertThat(JodaBeanUtils.mapValueType(test, Person.class)).isEqualTo(Address.class); } @Test void test_integerType_Person_mapKeyTypeInvalid() { MetaProperty test = ImmPerson.meta().age(); assertThat(JodaBeanUtils.mapKeyType(test, Person.class)).isNull(); assertThat(JodaBeanUtils.mapValueType(test, Person.class)).isNull(); } @Test void test_collectionType_Person_mapKeyTypeInvalid() { MetaProperty> test = Person.meta().addressList(); assertThat(JodaBeanUtils.mapKeyType(test, Person.class)).isNull(); assertThat(JodaBeanUtils.mapValueType(test, Person.class)).isNull(); } @Test void test_mapType_wildcard() { @SuppressWarnings("unchecked") MetaProperty> test = ImmGuava.meta().mapWildKey(); assertThat(JodaBeanUtils.mapKeyType(test, ImmGuava.class)).isEqualTo(Number.class); assertThat(JodaBeanUtils.mapValueType(test, ImmGuava.class)).isEqualTo(String.class); } //------------------------------------------------------------------------- @Test void test_mapValueTypeTypes_valid() { MetaProperty>> test = ImmAddress.meta().listNumericInMap(); List> expected = ImmutableList.>of(Integer.class); assertThat(JodaBeanUtils.mapValueTypeTypes(test, ImmAddress.class)).isEqualTo(expected); } @Test void test_mapValueTypeTypes_invalidNoGenerics() { MetaProperty> test = Person.meta().otherAddressMap(); List> expected = Collections.emptyList(); assertThat(JodaBeanUtils.mapValueTypeTypes(test, Person.class)).isEqualTo(expected); } @Test void test_mapValueTypeTypes_invalidNotMap() { MetaProperty> test = Person.meta().addressList(); List> expected = Collections.emptyList(); assertThat(JodaBeanUtils.mapValueTypeTypes(test, Person.class)).isEqualTo(expected); } //------------------------------------------------------------------------- @Test void equalIgnoring() { Bean bean1 = createBean("123", "321", "name1"); Bean bean2 = createBean("124", "321", "name1"); // first not ignored assertThat(JodaBeanUtils.equalIgnoring(bean1, bean2)).isFalse(); assertThat(JodaBeanUtils.equalIgnoring(bean1, bean2, bean1.metaBean().metaProperty("second"))).isFalse(); assertThat(JodaBeanUtils.equalIgnoring(bean1, bean2, bean1.metaBean().metaProperty("second"), bean1.metaBean().metaProperty("name"))).isFalse(); // first is ignored assertThat(JodaBeanUtils.equalIgnoring(bean1, bean2, bean1.metaBean().metaProperty("first"))).isTrue(); assertThat(JodaBeanUtils.equalIgnoring(bean1, bean2, bean1.metaBean().metaProperty("first"), bean1.metaBean().metaProperty("second"))).isTrue(); } @Test void equalIgnoring_same() { Bean bean1 = createBean("123", "321", "name1"); Bean bean2 = createBean("124", "321", "name1"); assertThat(JodaBeanUtils.equalIgnoring(bean1, bean1)).isTrue(); assertThat(JodaBeanUtils.equalIgnoring(bean2, bean2)).isTrue(); } @Test void equalIgnoring_nullFirst() { Bean bean = createBean("124", "321", "name1"); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.equalIgnoring(null, bean)); } @Test void equalIgnoring_nullSecond() { Bean bean = createBean("124", "321", "name1"); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.equalIgnoring(bean, null)); } @Test void equalIgnoring_nullArray() { Bean bean = createBean("124", "321", "name1"); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanUtils.equalIgnoring(bean, bean, (MetaProperty[]) null)); } private static Bean createBean(String first, String second, String name) { FlexiBean bean = new FlexiBean(); bean.propertySet("first", first); bean.propertySet("second", second); bean.propertySet("name", name); return bean; } //------------------------------------------------------------------------- @Test void test_compare_ascending() { Address address1 = new Address(); address1.setOwner(new Person()); address1.getOwner().setSurname("Joda"); Address address2 = new Address(); address2.setOwner(new Person()); address2.getOwner().setSurname("Beans"); Function bq = JodaBeanUtils.chain(Address.meta().owner(), Person.meta().surname()); Comparator asc = JodaBeanUtils.comparator(bq, true); assertThat(asc.compare(address1, address1) == 0).isTrue(); assertThat(asc.compare(address1, address2) > 1).isTrue(); assertThat(asc.compare(address2, address1) < 1).isTrue(); } @Test void test_compare_descending() { Address address1 = new Address(); address1.setOwner(new Person()); address1.getOwner().setSurname("Joda"); Address address2 = new Address(); address2.setOwner(new Person()); address2.getOwner().setSurname("Beans"); Function bq = JodaBeanUtils.chain(Address.meta().owner(), Person.meta().surname()); Comparator desc = JodaBeanUtils.comparator(bq, false); assertThat(desc.compare(address1, address1) == 0).isTrue(); assertThat(desc.compare(address1, address2) < 1).isTrue(); assertThat(desc.compare(address2, address1) > 1).isTrue(); } @Test void test_compare_ascending_null() { assertThatNullPointerException() .isThrownBy(() -> JodaBeanUtils.comparatorAscending(null)); } @Test void test_compare_descending_null() { assertThatNullPointerException() .isThrownBy(() -> JodaBeanUtils.comparatorDescending(null)); } } ================================================ FILE: src/test/java/org/joda/beans/TestLight.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.ArrayList; import java.util.Currency; import java.util.NoSuchElementException; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.LightImmutable; import org.joda.beans.sample.LightMutable; import org.joda.beans.ser.JodaBeanSer; import org.junit.jupiter.api.Test; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; /** * Test style=light. */ class TestLight { @Test void test_immutable() { ImmPerson person = ImmPerson.builder().forename("John").surname("Doggett").build(); LightImmutable bean = LightImmutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", LightImmutable.meta(), String.class), "Smallville") .set("owner", person) .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .set("hiddenText", "wow") .set("valueChar", 'a') // XML does not support char zero .build(); assertThat(bean.getNumber()).isEqualTo(12); assertThat(bean.getTown()).isEqualTo(Optional.absent()); assertThat(bean.getCity()).isEqualTo("Smallville"); assertThat(bean.getStreetName()).isEqualTo("Park Lane"); assertThat(bean.getOwner()).isEqualTo(person); assertThat(bean.getList()).isEqualTo(ImmutableList.of()); assertThat(bean.metaBean().beanType()).isEqualTo(LightImmutable.class); assertThat(bean.metaBean().metaPropertyCount()).isEqualTo(14); assertThat(bean.metaBean().metaPropertyExists("number")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("town")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("address")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("foobar")).isFalse(); assertThat(bean.metaBean().metaPropertyExists("place")).isFalse(); assertThat(bean.metaBean().metaProperty("place")).isEqualTo(bean.metaBean().metaProperty("city")); LightImmutable builtWithAlias = LightImmutable.meta().builder() .set("place", "Place") .set("street", "Park Lane") .set("owner", person) .build(); assertThat(builtWithAlias.getCity()).isEqualTo("Place"); MetaProperty mp = bean.metaBean().metaProperty("number"); assertThat(mp.propertyType()).isEqualTo(int.class); assertThat(mp.declaringType()).isEqualTo(LightImmutable.class); assertThat(mp.get(bean)).isEqualTo(12); assertThat(mp.style()).isEqualTo(PropertyStyle.IMMUTABLE); MetaProperty mp2 = bean.metaBean().metaProperty("town"); assertThat(mp2.propertyType()).isEqualTo(String.class); assertThat(mp2.propertyGenericType()).isEqualTo(String.class); assertThat(mp2.declaringType()).isEqualTo(LightImmutable.class); assertThat(mp2.get(bean)).isNull(); assertThat(mp2.style()).isEqualTo(PropertyStyle.IMMUTABLE); MetaProperty mp3 = bean.metaBean().metaProperty("address"); assertThat(mp3.propertyType()).isEqualTo(String.class); assertThat(mp3.propertyGenericType()).isEqualTo(String.class); assertThat(mp3.declaringType()).isEqualTo(LightImmutable.class); assertThat(mp3.get(bean)).isEqualTo("12 Park Lane Smallville"); assertThat(mp3.style()).isEqualTo(PropertyStyle.DERIVED); MetaProperty mp4 = bean.metaBean().metaProperty("hiddenText"); assertThat(mp4.propertyType()).isEqualTo(String.class); assertThat(mp4.propertyGenericType()).isEqualTo(String.class); assertThat(mp4.declaringType()).isEqualTo(LightImmutable.class); assertThat(mp4.get(bean)).isEqualTo("wow"); assertThat(mp4.style()).isEqualTo(PropertyStyle.IMMUTABLE); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).contains("USD<"); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).doesNotContain(""); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> LightImmutable.meta().builder().set(mp3, "Nothing")); } @Test void test_immutable_order() { ImmPerson person = ImmPerson.builder().forename("John").surname("Doggett").build(); LightImmutable bean = LightImmutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", LightImmutable.meta(), String.class), "Smallville") .set("owner", person) .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .build(); ImmutableList> mps = ImmutableList.copyOf(bean.metaBean().metaPropertyIterable()); assertThat(mps.get(0).name()).isEqualTo("number"); assertThat(mps.get(1).name()).isEqualTo("flag"); assertThat(mps.get(2).name()).isEqualTo("street"); assertThat(mps.get(3).name()).isEqualTo("town"); assertThat(mps.get(4).name()).isEqualTo("city"); assertThat(mps.get(5).name()).isEqualTo("owner"); assertThat(mps.get(6).name()).isEqualTo("list"); assertThat(mps.get(7).name()).isEqualTo("currency"); assertThat(mps.get(8).name()).isEqualTo("hiddenText"); assertThat(mps.get(9).name()).isEqualTo("valueLong"); assertThat(mps.get(10).name()).isEqualTo("valueShort"); assertThat(mps.get(11).name()).isEqualTo("valueChar"); assertThat(mps.get(12).name()).isEqualTo("valueByte"); assertThat(mps.get(13).name()).isEqualTo("address"); } @Test void test_mutable() { LightMutable bean = LightMutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", LightMutable.meta(), String.class), "Smallville") .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .set("hiddenText", "wow") .build(); assertThat(bean.getNumber()).isEqualTo(12); assertThat(bean.getTown()).isEqualTo(Optional.absent()); assertThat(bean.getCity()).isEqualTo("Smallville"); assertThat(bean.getStreetName()).isEqualTo("Park Lane"); assertThat(bean.getList()).isEqualTo(ImmutableList.of()); assertThat(bean.getCurrency()).isEqualTo(Optional.of(Currency.getInstance("USD"))); bean.setCity("Nodnol"); assertThat(bean.getCity()).isEqualTo("Nodnol"); bean.property("city").set("Paris"); assertThat(bean.getCity()).isEqualTo("Paris"); bean.metaBean().metaProperty("city").set(bean, "London"); assertThat(bean.getCity()).isEqualTo("London"); assertThat(bean.metaBean().beanType()).isEqualTo(LightMutable.class); assertThat(bean.metaBean().metaPropertyCount()).isEqualTo(9); assertThat(bean.metaBean().metaPropertyExists("number")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("town")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("address")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("foobar")).isFalse(); assertThat(bean.metaBean().metaPropertyExists("place")).isFalse(); assertThat(bean.metaBean().metaProperty("place")).isEqualTo(bean.metaBean().metaProperty("city")); LightMutable builtWithAlias = LightMutable.meta().builder() .set("place", "Place") .set("street", "Park Lane") .build(); assertThat(builtWithAlias.getCity()).isEqualTo("Place"); MetaProperty mp = bean.metaBean().metaProperty("number"); assertThat(mp.propertyType()).isEqualTo(int.class); assertThat(mp.declaringType()).isEqualTo(LightMutable.class); assertThat(mp.get(bean)).isEqualTo(12); assertThat(mp.style()).isEqualTo(PropertyStyle.READ_WRITE); MetaProperty mp2 = bean.metaBean().metaProperty("currency"); assertThat(mp2.propertyType()).isEqualTo(Currency.class); assertThat(mp2.propertyGenericType()).isEqualTo(Currency.class); assertThat(mp2.declaringType()).isEqualTo(LightMutable.class); assertThat(mp2.get(bean)).isEqualTo(Currency.getInstance("USD")); assertThat(mp2.style()).isEqualTo(PropertyStyle.READ_WRITE); MetaProperty mp3 = bean.metaBean().metaProperty("address"); assertThat(mp3.propertyType()).isEqualTo(String.class); assertThat(mp3.propertyGenericType()).isEqualTo(String.class); assertThat(mp3.declaringType()).isEqualTo(LightMutable.class); assertThat(mp3.get(bean)).isEqualTo("12 Park Lane London"); assertThat(mp3.style()).isEqualTo(PropertyStyle.DERIVED); MetaProperty mp4 = bean.metaBean().metaProperty("hiddenText"); assertThat(mp4.propertyType()).isEqualTo(String.class); assertThat(mp4.propertyGenericType()).isEqualTo(String.class); assertThat(mp4.declaringType()).isEqualTo(LightMutable.class); assertThat(mp4.get(bean)).isEqualTo("wow"); assertThat(mp4.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).contains("USD<"); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).doesNotContain(""); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> LightImmutable.meta().builder().set(mp3, "Nothing")); } } ================================================ FILE: src/test/java/org/joda/beans/TestMapBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.impl.map.MapBean; import org.junit.jupiter.api.Test; /** * Test {@link MapBean}. */ class TestMapBean { @Test void test_clone() { MapBean a = new MapBean(); a.put("A", "AA"); a.put("B", "BB"); MapBean b = a.clone(); assertThat(a.get("A")).isEqualTo("AA"); assertThat(a.get("B")).isEqualTo("BB"); assertThat(b.get("A")).isEqualTo("AA"); assertThat(b.get("B")).isEqualTo("BB"); a.clear(); assertThat(a.get("A")).isNull(); assertThat(a.get("B")).isNull(); assertThat(b.get("A")).isEqualTo("AA"); assertThat(b.get("B")).isEqualTo("BB"); } @Test void test_equalsHashCode() { MapBean a1 = new MapBean(); MapBean a2 = new MapBean(); MapBean b = new MapBean(); a1.put("first", "A"); a2.put("first", "A"); b.put("first", "B"); assertThat(a1.equals(a1)).isTrue(); assertThat(a1.equals(a2)).isTrue(); assertThat(a2.equals(a1)).isTrue(); assertThat(a2.equals(a2)).isTrue(); assertThat(a1.hashCode()).isEqualTo(a2.hashCode()); assertThat(a1.equals(b)).isFalse(); assertThat(b.equals(a1)).isFalse(); Object obj = "Weird type"; assertThat(b.equals(obj)).isFalse(); assertThat(b.equals(null)).isFalse(); } @Test void test_propertyDefine_propertyRemove() { MapBean mapBean = new MapBean(); assertThat(mapBean.propertyNames().size()).isEqualTo(0); mapBean.propertyDefine("name", String.class); assertThat(mapBean.propertyNames().size()).isEqualTo(1); Property prop = mapBean.property("name"); assertThat(prop.name()).isEqualTo("name"); assertThat(prop.get()).isNull(); mapBean.propertyRemove("name"); assertThat(mapBean.propertyNames().size()).isEqualTo(0); } @Test void test_metaBean() { MapBean mapBean = new MapBean(); DynamicMetaBean meta = mapBean.metaBean(); assertThat(meta.metaPropertyCount()).isEqualTo(0); meta.metaPropertyDefine("name", String.class); assertThat(meta.metaPropertyCount()).isEqualTo(1); MetaProperty prop = meta.metaProperty("name"); assertThat(prop.name()).isEqualTo("name"); assertThat(prop.get(mapBean)).isNull(); meta.metaPropertyDefine("name", String.class); assertThat(meta.metaPropertyCount()).isEqualTo(1); MetaProperty prop2 = meta.metaProperty("address"); assertThat(prop2).isNotNull(); assertThat(meta.metaPropertyCount()).isEqualTo(1); // meta-property object created but data not changed } } ================================================ FILE: src/test/java/org/joda/beans/TestMetaBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.impl.map.MapBean; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.MetaBeanLoad; import org.junit.jupiter.api.Test; /** * Test {@link MetaBean}. */ class TestMetaBean { //----------------------------------------------------------------------- @Test void test_registerMetaBean() { // register once OK assertThat(ImmPerson.meta()).isNotNull(); // register second time not OK assertThatIllegalArgumentException() .isThrownBy(() -> MetaBean.register(ImmPerson.meta())); } //----------------------------------------------------------------------- @Test void test_metaBean() { MetaBean metaBean = MetaBean.of(MetaBeanLoad.class); assertThat(metaBean).isNotNull(); assertThat(metaBean).isEqualTo(MetaBeanLoad.meta()); } @Test void test_metaBean_FlexiBean() { assertThat(MetaBean.of(FlexiBean.class).builder().build().getClass()).isEqualTo(FlexiBean.class); } @Test void test_metaBean_MapBean() { assertThat(MetaBean.of(MapBean.class).builder().build().getClass()).isEqualTo(MapBean.class); } @Test void test_metaBean_notFound() { assertThatIllegalArgumentException() .isThrownBy(() -> MetaBean.of(String.class)); } } ================================================ FILE: src/test/java/org/joda/beans/TestMetaBeanProvider.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; /** * A mock {@link MetaBeanProvider} for testing. */ class TestMetaBeanProvider implements MetaBeanProvider { @Override public MetaBean findMetaBean(Class cls) { if (cls.equals(AnnotatedBean.class)) { return new AnnotatedMetaBean(); } else { return null; } } } ================================================ FILE: src/test/java/org/joda/beans/TestMetaBeans.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import java.util.Map; import java.util.Set; import org.junit.jupiter.api.Test; /** * Test {@link MetaBeans}. */ class TestMetaBeans { @Test void test_metaBeanProviderAnnotation() { MetaBean metaBean = MetaBeans.lookup(AnnotatedBean.class); assertThat(metaBean).isInstanceOf(AnnotatedMetaBean.class); } } // -------------------------------------------------------------------------------------------------- @MetaProvider(TestMetaBeanProvider.class) class AnnotatedBean implements Bean { @Override public MetaBean metaBean() { throw new UnsupportedOperationException("This method is not needed for testing"); } @Override public Property property(String propertyName) { throw new UnsupportedOperationException("This method is not needed for testing"); } @Override public Set propertyNames() { throw new UnsupportedOperationException("This method is not needed for testing"); } } class AnnotatedMetaBean implements MetaBean { @Override public boolean isBuildable() { throw new UnsupportedOperationException("This method is not needed for testing"); } @Override public BeanBuilder builder() { throw new UnsupportedOperationException("This method is not needed for testing"); } @Override public Class beanType() { return AnnotatedBean.class; } @Override public Map> metaPropertyMap() { throw new UnsupportedOperationException("This method is not needed for testing"); } } ================================================ FILE: src/test/java/org/joda/beans/TestMetaInvoke.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.AbstractResult; import org.joda.beans.sample.Address; import org.joda.beans.sample.AddressResult; import org.joda.beans.sample.CompanyAddress; import org.joda.beans.sample.CompanyAddressMidResult; import org.joda.beans.sample.CompanyAddressResult; import org.joda.beans.sample.Documentation; import org.joda.beans.sample.DocumentationHolder; import org.joda.beans.sample.FinalFieldBean; import org.joda.beans.sample.GenericSubWrapper; import org.joda.beans.sample.GenericWrapperDocumentation; import org.joda.beans.sample.MidAbstractResult; import org.joda.beans.sample.NoGenEquals; import org.joda.beans.sample.NoProperties; import org.joda.beans.sample.Pair; import org.joda.beans.sample.Person; import org.joda.beans.sample.PersonDocumentation; import org.joda.beans.sample.RWOnlyBean; import org.joda.beans.sample.SubPerson; import org.joda.beans.sample.SubWrapper; import org.joda.beans.sample.TweakedPair; import org.joda.beans.sample.ValidateBean; import org.joda.beans.sample.Wrapper; import org.junit.jupiter.api.Test; /** * Test property using Person. */ class TestMetaInvoke { @Test void test_method_call_compiles() { @SuppressWarnings("unchecked") AbstractResult.Meta
a = AbstractResult.meta(); assertThat(a).isNotNull(); AbstractResult.Meta
a2 = AbstractResult.metaAbstractResult(Address.class); assertThat(a2).isNotNull(); Address.Meta b = Address.meta(); assertThat(b).isNotNull(); AddressResult.Meta c = AddressResult.meta(); assertThat(c).isNotNull(); CompanyAddress.Meta d = CompanyAddress.meta(); assertThat(d).isNotNull(); CompanyAddressMidResult.Meta e = CompanyAddressMidResult.meta(); assertThat(e).isNotNull(); CompanyAddressResult.Meta f = CompanyAddressResult.meta(); assertThat(f).isNotNull(); @SuppressWarnings("unchecked") Documentation.Meta g = Documentation.meta(); assertThat(g).isNotNull(); Documentation.Meta g2 = Documentation.metaDocumentation(String.class); assertThat(g2).isNotNull(); DocumentationHolder.Meta h = DocumentationHolder.meta(); assertThat(h).isNotNull(); FinalFieldBean.Meta i = FinalFieldBean.meta(); assertThat(i).isNotNull(); @SuppressWarnings("unchecked") GenericSubWrapper.Meta
j = GenericSubWrapper.meta(); assertThat(j).isNotNull(); GenericSubWrapper.Meta
j2 = GenericSubWrapper.metaGenericSubWrapper(Address.class); assertThat(j2).isNotNull(); @SuppressWarnings("unchecked") GenericWrapperDocumentation.Meta
k = GenericWrapperDocumentation.meta(); assertThat(k).isNotNull(); GenericWrapperDocumentation.Meta
k2 = GenericWrapperDocumentation.metaGenericWrapperDocumentation(Address.class); assertThat(k2).isNotNull(); @SuppressWarnings("unchecked") MidAbstractResult.Meta
l = MidAbstractResult.meta(); assertThat(l).isNotNull(); MidAbstractResult.Meta
l2 = MidAbstractResult.metaMidAbstractResult(Address.class); assertThat(l2).isNotNull(); NoGenEquals.Meta m = NoGenEquals.meta(); assertThat(m).isNotNull(); NoProperties.Meta n = NoProperties.meta(); assertThat(n).isNotNull(); Pair.Meta o = Pair.meta(); assertThat(o).isNotNull(); Person.Meta p = Person.meta(); assertThat(p).isNotNull(); PersonDocumentation.Meta q = PersonDocumentation.meta(); assertThat(q).isNotNull(); RWOnlyBean.Meta r = RWOnlyBean.meta(); assertThat(r).isNotNull(); @SuppressWarnings("unchecked") SubPerson.Meta s = SubPerson.meta(); assertThat(s).isNotNull(); SubPerson.Meta s2 = SubPerson.metaSubPerson(String.class); assertThat(s2).isNotNull(); SubWrapper.Meta t = SubWrapper.meta(); assertThat(t).isNotNull(); TweakedPair.Meta u = TweakedPair.meta(); assertThat(u).isNotNull(); ValidateBean.Meta v = ValidateBean.meta(); assertThat(v).isNotNull(); @SuppressWarnings("unchecked") Wrapper.Meta
w = Wrapper.meta(); assertThat(w).isNotNull(); } } ================================================ FILE: src/test/java/org/joda/beans/TestMinimal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.ArrayList; import java.util.Currency; import java.util.NoSuchElementException; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.LightImmutable; import org.joda.beans.sample.MinimalImmutable; import org.joda.beans.sample.MinimalMutable; import org.joda.beans.ser.JodaBeanSer; import org.junit.jupiter.api.Test; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; /** * Test style=minimal. */ class TestMinimal { @Test void test_immutable() { ImmPerson person = ImmPerson.builder().forename("John").surname("Doggett").build(); MinimalImmutable bean = MinimalImmutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", MinimalImmutable.meta(), String.class), "Smallville") .set("owner", person) .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .build(); assertThat(bean.getNumber()).isEqualTo(12); assertThat(bean.getTown()).isEqualTo(Optional.absent()); assertThat(bean.getCity()).isEqualTo("Smallville"); assertThat(bean.getStreetName()).isEqualTo("Park Lane"); assertThat(bean.getOwner()).isEqualTo(person); assertThat(bean.getList()).isEqualTo(ImmutableList.of()); assertThat(bean.metaBean().beanType()).isEqualTo(MinimalImmutable.class); assertThat(bean.metaBean().metaPropertyCount()).isEqualTo(9); assertThat(bean.metaBean().metaPropertyExists("number")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("town")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("address")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("foobar")).isFalse(); assertThat(bean.metaBean().metaPropertyExists("place")).isFalse(); assertThat(bean.metaBean().metaProperty("place")).isEqualTo(bean.metaBean().metaProperty("city")); MinimalImmutable builtWithAlias = MinimalImmutable.meta().builder() .set("place", "Place") .set("street", "Park Lane") .set("owner", person) .build(); assertThat(builtWithAlias.getCity()).isEqualTo("Place"); MetaProperty mp = bean.metaBean().metaProperty("number"); assertThat(mp.propertyType()).isEqualTo(int.class); assertThat(mp.declaringType()).isEqualTo(MinimalImmutable.class); assertThat(mp.get(bean)).isEqualTo(12); assertThat(mp.style()).isEqualTo(PropertyStyle.IMMUTABLE); MetaProperty mp2 = bean.metaBean().metaProperty("town"); assertThat(mp2.propertyType()).isEqualTo(String.class); assertThat(mp2.propertyGenericType()).isEqualTo(String.class); assertThat(mp2.declaringType()).isEqualTo(MinimalImmutable.class); assertThat(mp2.get(bean)).isNull(); assertThat(mp2.style()).isEqualTo(PropertyStyle.IMMUTABLE); MetaProperty mp3 = bean.metaBean().metaProperty("address"); assertThat(mp3.propertyType()).isEqualTo(String.class); assertThat(mp3.propertyGenericType()).isEqualTo(String.class); assertThat(mp3.declaringType()).isEqualTo(MinimalImmutable.class); assertThat(mp3.get(bean)).isEqualTo("12 Park Lane Smallville"); assertThat(mp3.style()).isEqualTo(PropertyStyle.DERIVED); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).contains("USD<"); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).doesNotContain(""); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> LightImmutable.meta().builder().set(mp3, "Nothing")); } @Test void test_immutable_order() { ImmPerson person = ImmPerson.builder().forename("John").surname("Doggett").build(); MinimalImmutable bean = MinimalImmutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", MinimalImmutable.meta(), String.class), "Smallville") .set("owner", person) .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .build(); ImmutableList> mps = ImmutableList.copyOf(bean.metaBean().metaPropertyIterable()); assertThat(mps.get(0).name()).isEqualTo("number"); assertThat(mps.get(1).name()).isEqualTo("flag"); assertThat(mps.get(2).name()).isEqualTo("street"); assertThat(mps.get(3).name()).isEqualTo("town"); assertThat(mps.get(4).name()).isEqualTo("city"); assertThat(mps.get(5).name()).isEqualTo("owner"); assertThat(mps.get(6).name()).isEqualTo("list"); assertThat(mps.get(7).name()).isEqualTo("currency"); assertThat(mps.get(8).name()).isEqualTo("address"); } @Test void test_mutable() { MinimalMutable bean = MinimalMutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", MinimalMutable.meta(), String.class), "Smallville") .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .build(); assertThat(bean.getNumber()).isEqualTo(12); assertThat(bean.getTown()).isEqualTo(Optional.absent()); assertThat(bean.getCity()).isEqualTo("Smallville"); assertThat(bean.getStreetName()).isEqualTo("Park Lane"); assertThat(bean.getList()).isEqualTo(ImmutableList.of()); assertThat(bean.getCurrency()).isEqualTo(Optional.of(Currency.getInstance("USD"))); bean.setCity("Nodnol"); assertThat(bean.getCity()).isEqualTo("Nodnol"); bean.property("city").set("Paris"); assertThat(bean.getCity()).isEqualTo("Paris"); bean.metaBean().metaProperty("city").set(bean, "London"); assertThat(bean.getCity()).isEqualTo("London"); assertThat(bean.metaBean().beanType()).isEqualTo(MinimalMutable.class); assertThat(bean.metaBean().metaPropertyCount()).isEqualTo(8); assertThat(bean.metaBean().metaPropertyExists("number")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("town")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("address")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("foobar")).isFalse(); assertThat(bean.metaBean().metaPropertyExists("place")).isFalse(); assertThat(bean.metaBean().metaProperty("place")).isEqualTo(bean.metaBean().metaProperty("city")); MinimalMutable builtWithAlias = MinimalMutable.meta().builder() .set("place", "Place") .set("street", "Park Lane") .build(); assertThat(builtWithAlias.getCity()).isEqualTo("Place"); MetaProperty mp = bean.metaBean().metaProperty("number"); assertThat(mp.propertyType()).isEqualTo(int.class); assertThat(mp.declaringType()).isEqualTo(MinimalMutable.class); assertThat(mp.get(bean)).isEqualTo(12); assertThat(mp.style()).isEqualTo(PropertyStyle.READ_WRITE); MetaProperty mp2 = bean.metaBean().metaProperty("currency"); assertThat(mp2.propertyType()).isEqualTo(Currency.class); assertThat(mp2.propertyGenericType()).isEqualTo(Currency.class); assertThat(mp2.declaringType()).isEqualTo(MinimalMutable.class); assertThat(mp2.get(bean)).isEqualTo(Currency.getInstance("USD")); assertThat(mp2.style()).isEqualTo(PropertyStyle.READ_WRITE); MetaProperty mp3 = bean.metaBean().metaProperty("address"); assertThat(mp3.propertyType()).isEqualTo(String.class); assertThat(mp3.propertyGenericType()).isEqualTo(String.class); assertThat(mp3.declaringType()).isEqualTo(MinimalMutable.class); assertThat(mp3.get(bean)).isEqualTo("12 Park Lane London"); assertThat(mp3.style()).isEqualTo(PropertyStyle.DERIVED); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).contains("USD<"); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).doesNotContain(""); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> LightImmutable.meta().builder().set(mp3, "Nothing")); } @Test void test_mutable_order() { MinimalMutable bean = MinimalMutable.meta().builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", MinimalMutable.meta(), String.class), "Smallville") .set("list", new ArrayList()) .set("currency", Currency.getInstance("USD")) .build(); ImmutableList> mps = ImmutableList.copyOf(bean.metaBean().metaPropertyIterable()); assertThat(mps.get(0).name()).isEqualTo("number"); assertThat(mps.get(1).name()).isEqualTo("flag"); assertThat(mps.get(2).name()).isEqualTo("street"); assertThat(mps.get(3).name()).isEqualTo("town"); assertThat(mps.get(4).name()).isEqualTo("city"); assertThat(mps.get(5).name()).isEqualTo("list"); assertThat(mps.get(6).name()).isEqualTo("currency"); assertThat(mps.get(7).name()).isEqualTo("address"); } } ================================================ FILE: src/test/java/org/joda/beans/TestMutableDerived.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.MutableDerivedBean; import org.junit.jupiter.api.Test; /** * Test mutable derived beans. */ class TestMutableDerived { @Test void test_mutableDerivedBean() { MutableDerivedBean test = (MutableDerivedBean) MutableDerivedBean.builder() .baseBeanString("HopeNotHate") .build(); assertThat(test.getBaseBeanString()).isEqualTo("HopeNotHate"); assertThat(test.metaBean().metaPropertyCount()).isEqualTo(1); assertThat(test.metaBean().metaPropertyMap().keySet().iterator().next()).isEqualTo("baseBeanString"); assertThat(test.metaBean().baseBeanString().get(test)).isEqualTo("HopeNotHate"); test.metaBean().baseBeanString().set(test, "Now"); assertThat(test.getBaseBeanString()).isEqualTo("Now"); assertThat(test.metaBean().baseBeanString().get(test)).isEqualTo("Now"); test.metaBean().baseBeanString().setString(test, "Please"); assertThat(test.getBaseBeanString()).isEqualTo("Please"); assertThat(test.metaBean().baseBeanString().get(test)).isEqualTo("Please"); } @Test void test_mutableDerivedBean_builder() { MutableDerivedBean test = MutableDerivedBean.builder() .set("baseBeanString", "HopeNotHate") .build(); assertThat(test.getBaseBeanString()).isEqualTo("HopeNotHate"); assertThat(test.metaBean().metaPropertyCount()).isEqualTo(1); assertThat(test.metaBean().metaPropertyMap().keySet().iterator().next()).isEqualTo("baseBeanString"); assertThat(test.metaBean().baseBeanString().get(test)).isEqualTo("HopeNotHate"); } } ================================================ FILE: src/test/java/org/joda/beans/TestMutableListBeans.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.MutableListFinalBean; import org.joda.beans.sample.MutableListNonFinalBean; import org.junit.jupiter.api.Test; /** * Test list with builder. */ class TestMutableListBeans { @Test void test_finalBean_noList() { MutableListFinalBean test = MutableListFinalBean.builder().build(); assertThat(test.getStrings()).isNull(); } @Test void test_finalBean_list() { MutableListFinalBean test = MutableListFinalBean.builder().strings("A", "B").build(); assertThat(test.getStrings()).containsExactly("A", "B"); } @Test void test_nonFinalBean_noList() { MutableListNonFinalBean test = MutableListNonFinalBean.builder().build(); assertThat(test.getStrings()).isNull(); } @Test void test_nonFinalBean_list() { MutableListNonFinalBean test = MutableListNonFinalBean.builder().strings("A", "B").build(); assertThat(test.getStrings()).containsExactly("A", "B"); } } ================================================ FILE: src/test/java/org/joda/beans/TestOptionalBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.ImmOptionalMeta; import org.junit.jupiter.api.Test; import com.google.common.base.Optional; /** * Test ImmOptional. */ class TestOptionalBean { @Test void test_optional_empty() { ImmOptional test = ImmOptional.builder() .optString(Optional.of("A")) .optStringGetter("A") .build(); assertThat(test.getOptString()).isEqualTo(Optional.of("A")); assertThat(test.getOptStringGetter()).isEqualTo(Optional.of("A")); assertThat(test.getOptDoubleGetter()).isEqualTo(Optional.absent()); assertThat(test.getOptIntGetter()).isEqualTo(Optional.absent()); assertThat(test.getOptLongGetter()).isEqualTo(Optional.absent()); // check that meta bean can be assigned to the metaImplements interface ImmOptionalMeta meta1 = ImmOptional.meta(); ImmOptionalMeta meta2 = test.metaBean(); assertThat(meta1.optString().get(test)).isEqualTo(Optional.of("A")); assertThat(meta1.optStringGetter().get(test)).isEqualTo("A"); assertThat(meta2.optDoubleGetter().get(test)).isNull(); } @Test void test_optional_full() { ImmOptional test = ImmOptional.builder() .optString(Optional.of("A")) .optDoubleGetter(1.2d) .optIntGetter(3) .optLongGetter(4L) .build(); assertThat(test.getOptString()).isEqualTo(Optional.of("A")); assertThat(test.getOptDoubleGetter()).isEqualTo(Optional.of(1.2d)); assertThat(test.getOptIntGetter()).isEqualTo(Optional.of(3)); assertThat(test.getOptLongGetter()).isEqualTo(Optional.of(4L)); } @Test void test_optional_property() { ImmOptional test = ImmOptional.builder() .optStringGetter("A") .build(); assertThat(test.getOptStringGetter()).isEqualTo(Optional.of("A")); MetaProperty mp2 = test.metaBean().metaProperty("optStringGetter"); assertThat(mp2.propertyType()).isEqualTo(String.class); assertThat(mp2.propertyGenericType()).isEqualTo(String.class); assertThat(mp2.declaringType()).isEqualTo(ImmOptional.class); assertThat(mp2.get(test)).isEqualTo("A"); assertThat(mp2.style()).isEqualTo(PropertyStyle.IMMUTABLE); } } ================================================ FILE: src/test/java/org/joda/beans/TestPair.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.Pair; import org.joda.beans.sample.TweakedPair; import org.junit.jupiter.api.Test; /** * Test Pair. */ class TestPair { @Test void test_equalsHashCode() { // even though TwekedPair adds no new properties, we treat it as different // this can be avoided (see Git history) but at a performance cost Pair a1 = new Pair(); Pair a2 = new Pair(); TweakedPair b = new TweakedPair(); a1.setFirst("A"); a2.setFirst("A"); b.setFirst("A"); assertThat(a1.equals(a1)).isTrue(); assertThat(a1.equals(a2)).isTrue(); assertThat(a2.equals(a1)).isTrue(); assertThat(a2.equals(a2)).isTrue(); assertThat(a1.hashCode()).isEqualTo(a2.hashCode()); assertThat(a1.equals(b)).isFalse(); assertThat(b.equals(a1)).isFalse(); Object obj = "Weird type"; assertThat(b.equals(obj)).isFalse(); assertThat(b.equals(null)).isFalse(); } @Test void test_toString() { Pair test = new Pair(); test.setFirst("A"); test.setSecond("B"); assertThat(test).hasToString("Pair{first=A, second=B}"); } } ================================================ FILE: src/test/java/org/joda/beans/TestPerson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.AbstractResult; import org.joda.beans.sample.Address; import org.joda.beans.sample.ClassAnnotation; import org.joda.beans.sample.Person; import org.joda.beans.sample.SimpleAnnotation; import org.junit.jupiter.api.Test; /** * Test property using Person. */ class TestPerson { private static final int NUM_PROPERTIES = 8; private static final String FORENAME = "forename"; private static final String SURNAME = "surname"; private static final String NUMBER_OF_CARS = "numberOfCars"; @Test void test_bean() { Bean test = Person.meta().builder().build(); assertThat(test instanceof Person).isTrue(); assertThat(test.metaBean()).isEqualTo(Person.meta()); assertThat(test.propertyNames().contains(FORENAME)).isTrue(); assertThat(test.propertyNames().contains(SURNAME)).isTrue(); assertThat(test.propertyNames().contains(NUMBER_OF_CARS)).isTrue(); assertThat(test.propertyNames().contains("Rubbish")).isFalse(); assertThat(test.property(FORENAME).name()).isEqualTo(FORENAME); assertThat(test.property(SURNAME).name()).isEqualTo(SURNAME); assertThat(test.property(NUMBER_OF_CARS).name()).isEqualTo(NUMBER_OF_CARS); } @Test void test_bean_invalidPropertyName() { Bean test = Person.meta().builder().build(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.property("Rubbish")); } //----------------------------------------------------------------------- @Test void test_metaBean() { MetaBean test = Person.meta(); assertThat(test.isBuildable()).isTrue(); assertThat(test.beanType()).isEqualTo(Person.class); assertThat(test.beanName()).isEqualTo(Person.class.getName()); assertThat(test.metaPropertyCount()).isEqualTo(NUM_PROPERTIES); assertThat(test.metaPropertyExists(FORENAME)).isTrue(); assertThat(test.metaPropertyExists(SURNAME)).isTrue(); assertThat(test.metaPropertyExists(NUMBER_OF_CARS)).isTrue(); assertThat(test.metaPropertyExists("Rubbish")).isFalse(); assertThat(test.metaProperty(FORENAME).name()).isEqualTo(FORENAME); assertThat(test.metaProperty(SURNAME).name()).isEqualTo(SURNAME); assertThat(test.metaProperty(NUMBER_OF_CARS).name()).isEqualTo(NUMBER_OF_CARS); Map> map = test.metaPropertyMap(); assertThat(map.size()).isEqualTo(NUM_PROPERTIES); assertThat(map.containsKey(FORENAME)).isTrue(); assertThat(map.containsKey(SURNAME)).isTrue(); assertThat(map.containsKey(NUMBER_OF_CARS)).isTrue(); } @Test void test_metaBean_invalidPropertyName() { MetaBean test = Person.meta(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.metaProperty("Rubbish")); } @Test void test_metaProperty_annotation_notFound() { MetaProperty prop = Person.meta().extensions(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> prop.annotation(ClassAnnotation.class)); assertThat(prop.annotationOpt(ClassAnnotation.class)).isEmpty(); } @Test void test_metaBean_abstract() { MetaBean test = AbstractResult.meta(); assertThat(test.isBuildable()).isFalse(); assertThat(test.beanType()).isEqualTo(AbstractResult.class); assertThat(test.beanName()).isEqualTo(AbstractResult.class.getName()); assertThat(test.metaPropertyCount()).isEqualTo(2); assertThat(test.metaPropertyExists("docs")).isTrue(); assertThat(test.metaPropertyExists("Rubbish")).isFalse(); } //----------------------------------------------------------------------- @Test void test_namedPropertyMethod() { Person person = new Person(); Property test = person.forename(); assertThat((Object) test.bean()).isSameAs(person); assertThat(test.metaProperty()).isSameAs(Person.meta().forename()); assertThat(test.get()).isNull(); person.setForename("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_property_String() { Person person = new Person(); Property test = person.property(FORENAME); assertThat((Object) test.bean()).isSameAs(person); assertThat(test.metaProperty()).isSameAs(Person.meta().forename()); assertThat(test.get()).isNull(); person.setForename("A"); assertThat(test.get()).isEqualTo("A"); test.set("B"); assertThat(test.get()).isEqualTo("B"); assertThat(test.put("C")).isEqualTo("B"); assertThat(test.get()).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_namedMetaPropertyMethod() { Person person = new Person(); MetaProperty test = Person.meta().forename(); assertThat(test.metaBean().beanType()).isEqualTo(Person.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isSameAs(FORENAME); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(person)).isNull(); person.setForename("A"); assertThat(test.get(person)).isEqualTo("A"); test.set(person, "B"); assertThat(test.get(person)).isEqualTo("B"); assertThat(test.put(person, "C")).isEqualTo("B"); assertThat(test.get(person)).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_metaProperty_String() { Person person = new Person(); MetaProperty test = Person.meta().metaProperty(FORENAME); assertThat(test.metaBean().beanType()).isEqualTo(Person.class); assertThat(test.propertyType()).isEqualTo(String.class); assertThat(test.name()).isSameAs(FORENAME); assertThat(test.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(test.get(person)).isNull(); person.setForename("A"); assertThat(test.get(person)).isEqualTo("A"); test.set(person, "B"); assertThat(test.get(person)).isEqualTo("B"); assertThat(test.put(person, "C")).isEqualTo("B"); assertThat(test.get(person)).isEqualTo("C"); } //----------------------------------------------------------------------- @Test void test_metaProperty_types_addressList() { MetaProperty> test = Person.meta().addressList(); assertThat(test.metaBean().beanType()).isEqualTo(Person.class); assertThat(test.propertyType()).isEqualTo(List.class); assertThat(test.propertyGenericType()).isInstanceOf(ParameterizedType.class); ParameterizedType pt = (ParameterizedType) test.propertyGenericType(); assertThat(pt.getRawType()).isEqualTo(List.class); assertThat(pt.getOwnerType()).isNull(); Type[] actualTypes = pt.getActualTypeArguments(); assertThat(actualTypes.length).isEqualTo(1); assertThat(actualTypes[0]).isEqualTo(Address.class); } @Test void test_BeanUtils_addressList() { MetaProperty> test = Person.meta().addressList(); assertThat(test.metaBean().beanType()).isEqualTo(Person.class); assertThat(test.propertyType()).isEqualTo(List.class); assertThat(test.propertyGenericType()).isInstanceOf(ParameterizedType.class); ParameterizedType pt = (ParameterizedType) test.propertyGenericType(); assertThat(pt.getRawType()).isEqualTo(List.class); assertThat(pt.getOwnerType()).isNull(); Type[] actualTypes = pt.getActualTypeArguments(); assertThat(actualTypes.length).isEqualTo(1); assertThat(actualTypes[0]).isEqualTo(Address.class); } @Test void test_metaProperty_types_otherAddressMap() { MetaProperty> test = Person.meta().otherAddressMap(); assertThat(test.metaBean().beanType()).isEqualTo(Person.class); assertThat(test.propertyType()).isEqualTo(Map.class); assertThat(test.propertyGenericType()).isInstanceOf(ParameterizedType.class); ParameterizedType pt = (ParameterizedType) test.propertyGenericType(); assertThat(pt.getRawType()).isEqualTo(Map.class); assertThat(pt.getOwnerType()).isNull(); Type[] actualTypes = pt.getActualTypeArguments(); assertThat(actualTypes.length).isEqualTo(2); assertThat(actualTypes[0]).isEqualTo(String.class); assertThat(actualTypes[1]).isEqualTo(Address.class); } @Test void test_metaProperty_annotations_addressList() { MetaProperty> prop = Person.meta().addressList(); List test = prop.annotations(); assertThat(test.size()).isEqualTo(1); assertThat(test.get(0) instanceof PropertyDefinition).isTrue(); } @Test void test_metaProperty_annotations_extensions() { MetaProperty prop = Person.meta().extensions(); List annos = prop.annotations(); assertThat(annos.size()).isEqualTo(2); assertThat(annos.get(0) instanceof PropertyDefinition).isTrue(); assertThat(annos.get(1) instanceof SimpleAnnotation).isTrue(); assertThat(prop.annotation(PropertyDefinition.class).get()).isEqualTo("smart"); assertThat(prop.annotationOpt(PropertyDefinition.class)).isPresent(); assertThat(prop.annotationOpt(SimpleAnnotation.class)).isPresent(); } @Test void test_metaBean_annotations() { Person.Meta meta = Person.meta(); List annos = meta.annotations(); assertThat(annos.size()).isEqualTo(2); assertThat(annos.get(0) instanceof BeanDefinition).isTrue(); assertThat(annos.get(1) instanceof ClassAnnotation).isTrue(); assertThat(meta.annotation(BeanDefinition.class).builderScope()).isEqualTo("smart"); } } ================================================ FILE: src/test/java/org/joda/beans/TestPropertyPath.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.Person; import org.junit.jupiter.api.Test; /** * Test {@link PropertyPath}. */ class TestPropertyPath { //------------------------------------------------------------------------- @Test void test_get() { Person person1 = new Person(); person1.setForename("Angus"); Address address1 = new Address(); address1.setNumber(1); address1.setOwner(person1); Person person2 = new Person(); person2.setForename("Bob"); Address address2 = new Address(); address2.setNumber(2); address2.setOwner(person2); Map addrMap = new HashMap<>(); addrMap.put("Main", address1); addrMap.put("Other", address2); Date date = new Date(); ImmPerson base = ImmPerson.builder() .forename("Zach") .surname("Tidy") .dateOfBirth(date) .mainAddress(ImmAddress.builder() .street("My Street") .city("Nodnol") .owner(ImmPerson.builder() .forename("Zoe") .surname("Tidy") .build()) .build()) .addressList(address1, address2) .otherAddressMap(addrMap) .build(); assertThatIllegalArgumentException().isThrownBy(() -> PropertyPath.of("rubbish[]", String.class)); assertThat(PropertyPath.of("rubbish", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("rubbish[0]", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("rubbish[-1]", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("rubbish[Main]", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("forename", String.class).get(base)).hasValue("Zach"); assertThat(PropertyPath.of("forename.rubbish", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("surname", String.class).get(base)).hasValue("Tidy"); assertThat(PropertyPath.of("dateOfBirth", Date.class).get(base)).hasValue(date); assertThat(PropertyPath.of("mainAddress.city", String.class).get(base)).hasValue("Nodnol"); assertThat(PropertyPath.of("mainAddress[0].city", String.class).get(base)).hasValue("Nodnol"); assertThat(PropertyPath.of("mainAddress[1].city", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("mainAddress[-1].city", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("mainAddress[Other].city", String.class).get(base)).isEmpty(); assertThat(PropertyPath.of("addressList", Address.class).get(base)).hasValue(address1); assertThat(PropertyPath.of("addressList[0]", Address.class).get(base)).hasValue(address1); assertThat(PropertyPath.of("addressList[1]", Address.class).get(base)).hasValue(address2); assertThat(PropertyPath.of("addressList[2]", Address.class).get(base)).isEmpty(); assertThat(PropertyPath.of("addressList[-1]", Address.class).get(base)).isEmpty(); assertThat(PropertyPath.of("addressList[Main]", Address.class).get(base)).isEmpty(); assertThat(PropertyPath.of("otherAddressMap", Address.class).get(base)).hasValue(address1); assertThat(PropertyPath.of("otherAddressMap[Main]", Address.class).get(base)).hasValue(address1); assertThat(PropertyPath.of("otherAddressMap[Other]", Address.class).get(base)).hasValue(address2); assertThat(PropertyPath.of("otherAddressMap[Rubbish]", Address.class).get(base)).isEmpty(); assertThat(PropertyPath.of("otherAddressMap.number", Integer.class).get(base)).hasValue(1); assertThat(PropertyPath.of("otherAddressMap[Main].number", Integer.class).get(base)).hasValue(1); assertThat(PropertyPath.of("otherAddressMap[Other].number", Integer.class).get(base)).hasValue(2); assertThat(PropertyPath.of("otherAddressMap.owner.forename", String.class).get(base)).hasValue("Angus"); assertThat(PropertyPath.of("otherAddressMap[Other].owner.forename", String.class).get(base)).hasValue("Bob"); assertThat(PropertyPath.of("otherAddressMap[Other].owner.forename", String.class)) .hasToString("otherAddressMap[Other].owner.forename: java.lang.String"); } } ================================================ FILE: src/test/java/org/joda/beans/TestPropertyStyle.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; /** * Test {@link PropertyStyle}. */ class TestPropertyStyle { @Test void test_READ_ONLY() { assertThat(PropertyStyle.READ_ONLY.isReadable()).isTrue(); assertThat(PropertyStyle.READ_ONLY.isWritable()).isFalse(); assertThat(PropertyStyle.READ_ONLY.isBuildable()).isFalse(); assertThat(PropertyStyle.READ_ONLY.isReadOnly()).isTrue(); assertThat(PropertyStyle.READ_ONLY.isDerived()).isFalse(); assertThat(PropertyStyle.READ_ONLY.isSerializable()).isFalse(); } @Test void test_READ_WRITE() { assertThat(PropertyStyle.READ_WRITE.isReadable()).isTrue(); assertThat(PropertyStyle.READ_WRITE.isWritable()).isTrue(); assertThat(PropertyStyle.READ_WRITE.isBuildable()).isTrue(); assertThat(PropertyStyle.READ_WRITE.isReadOnly()).isFalse(); assertThat(PropertyStyle.READ_WRITE.isDerived()).isFalse(); assertThat(PropertyStyle.READ_WRITE.isSerializable()).isTrue(); } @Test void test_WRITE_ONLY() { assertThat(PropertyStyle.WRITE_ONLY.isReadable()).isFalse(); assertThat(PropertyStyle.WRITE_ONLY.isWritable()).isTrue(); assertThat(PropertyStyle.WRITE_ONLY.isBuildable()).isTrue(); assertThat(PropertyStyle.WRITE_ONLY.isReadOnly()).isFalse(); assertThat(PropertyStyle.WRITE_ONLY.isDerived()).isFalse(); assertThat(PropertyStyle.WRITE_ONLY.isSerializable()).isFalse(); } @Test void test_DERIVED() { assertThat(PropertyStyle.DERIVED.isReadable()).isTrue(); assertThat(PropertyStyle.DERIVED.isWritable()).isFalse(); assertThat(PropertyStyle.DERIVED.isBuildable()).isFalse(); assertThat(PropertyStyle.DERIVED.isReadOnly()).isTrue(); assertThat(PropertyStyle.DERIVED.isDerived()).isTrue(); assertThat(PropertyStyle.DERIVED.isSerializable()).isFalse(); } @Test void test_IMMUTABLE() { assertThat(PropertyStyle.IMMUTABLE.isReadable()).isTrue(); assertThat(PropertyStyle.IMMUTABLE.isWritable()).isFalse(); assertThat(PropertyStyle.IMMUTABLE.isBuildable()).isTrue(); assertThat(PropertyStyle.IMMUTABLE.isReadOnly()).isTrue(); assertThat(PropertyStyle.IMMUTABLE.isDerived()).isFalse(); assertThat(PropertyStyle.IMMUTABLE.isSerializable()).isTrue(); } } ================================================ FILE: src/test/java/org/joda/beans/TestRecordBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.lang.invoke.MethodHandles; import java.util.NoSuchElementException; import org.joda.beans.impl.RecordBean; import org.joda.beans.sample.Pair; import org.joda.beans.sample.RecordStrIntPair; import org.joda.beans.ser.JodaBeanSer; import org.junit.jupiter.api.Test; /** * Test RecordBean. */ class TestRecordBean { private static record StringLongPair(String first, long second) implements RecordBean { static { RecordBean.register(StringLongPair.class, MethodHandles.lookup()); } } @Test void test_metaBean_public() { var test = new RecordStrIntPair("A", 1); assertThat(test.first()).isEqualTo("A"); assertThat(test.second()).isEqualTo(1); var meta = test.metaBean(); assertThat(meta.isBuildable()).isTrue(); assertThat(meta.beanType()).isEqualTo(RecordStrIntPair.class); assertThat(meta.metaPropertyCount()).isEqualTo(2); var mp1 = meta.metaProperty("first"); assertThat(mp1.name()).isEqualTo("first"); assertThat(mp1.declaringType()).isEqualTo(RecordStrIntPair.class); assertThat(mp1.metaBean()).isSameAs(meta); assertThat(mp1.get(test)).isEqualTo("A"); assertThat(mp1.propertyType()).isEqualTo(String.class); assertThat(mp1.style()).isEqualTo(PropertyStyle.IMMUTABLE); var mp2 = meta.metaProperty("second"); assertThat(mp2.name()).isEqualTo("second"); assertThat(mp2.declaringType()).isEqualTo(RecordStrIntPair.class); assertThat(mp2.metaBean()).isSameAs(meta); assertThat(mp2.get(test)).isEqualTo(1); assertThat(mp2.propertyType()).isEqualTo(int.class); assertThat(mp2.style()).isEqualTo(PropertyStyle.IMMUTABLE); assertThat(mp1).isEqualTo(mp1) .isNotEqualTo(mp2) .isNotEqualTo("") .isNotEqualTo(Pair.meta().first()) .hasSameHashCodeAs(mp1) .doesNotHaveSameHashCodeAs(mp2); var builder = meta.builder(); builder.set("first", "B"); builder.set("second", 2); assertThat(builder.get("first")).isEqualTo("B"); assertThat(builder.get(mp1)).isEqualTo("B"); assertThat(builder.build()).isEqualTo(new RecordStrIntPair("B", 2)); builder.set(mp1, "A"); assertThat(builder.build()).isEqualTo(new RecordStrIntPair("A", 2)); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.get("foo")); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.set("foo", "")); var json = JodaBeanSer.PRETTY.jsonWriter().write(test); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); assertThat(parsed).isEqualTo(test); } @Test void test_metaBean_private() { var test = new StringLongPair("A", 1L); assertThat(test.first()).isEqualTo("A"); assertThat(test.second()).isEqualTo(1L); var meta = test.metaBean(); assertThat(meta.isBuildable()).isTrue(); assertThat(meta.beanType()).isEqualTo(StringLongPair.class); assertThat(meta.metaPropertyCount()).isEqualTo(2); var mp1 = meta.metaProperty("first"); assertThat(mp1.name()).isEqualTo("first"); assertThat(mp1.declaringType()).isEqualTo(StringLongPair.class); assertThat(mp1.metaBean()).isSameAs(meta); assertThat(mp1.get(test)).isEqualTo("A"); assertThat(mp1.propertyType()).isEqualTo(String.class); assertThat(mp1.style()).isEqualTo(PropertyStyle.IMMUTABLE); var mp2 = meta.metaProperty("second"); assertThat(mp2.name()).isEqualTo("second"); assertThat(mp2.declaringType()).isEqualTo(StringLongPair.class); assertThat(mp2.metaBean()).isSameAs(meta); assertThat(mp2.get(test)).isEqualTo(1L); assertThat(mp2.propertyType()).isEqualTo(long.class); assertThat(mp2.style()).isEqualTo(PropertyStyle.IMMUTABLE); assertThat(mp1).isEqualTo(mp1) .isNotEqualTo(mp2) .isNotEqualTo("") .isNotEqualTo(Pair.meta().first()) .hasSameHashCodeAs(mp1) .doesNotHaveSameHashCodeAs(mp2); var builder = meta.builder(); builder.set("first", "B"); builder.set("second", 2L); assertThat(builder.get("first")).isEqualTo("B"); assertThat(builder.get(mp1)).isEqualTo("B"); assertThat(builder.build()).isEqualTo(new StringLongPair("B", 2L)); builder.set(mp1, "A"); assertThat(builder.build()).isEqualTo(new StringLongPair("A", 2L)); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.get("foo")); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> builder.set("foo", "")); var json = JodaBeanSer.PRETTY.jsonWriter().write(test); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); assertThat(parsed).isEqualTo(test); } } ================================================ FILE: src/test/java/org/joda/beans/TestReflective.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.sample.ReflectiveMutable; import org.joda.beans.ser.JodaBeanSer; import org.junit.jupiter.api.Test; /** * Test {@code ReflectiveMetaBean}. */ class TestReflective { @Test void test_mutable() { ReflectiveMutable bean = ReflectiveMutable.META_BEAN.builder() .set("number", 12) .set("street", "Park Lane") .set(StandaloneMetaProperty.of("city", ReflectiveMutable.META_BEAN, String.class), "Smallville") .build(); assertThat(bean.getNumber()).isEqualTo(12); assertThat(bean.getCity()).isEqualTo("Smallville"); assertThat(bean.getStreet()).isEqualTo("Park Lane"); bean.setCity("Nodnol"); assertThat(bean.getCity()).isEqualTo("Nodnol"); bean.property("city").set("Paris"); assertThat(bean.getCity()).isEqualTo("Paris"); bean.metaBean().metaProperty("city").set(bean, "London"); assertThat(bean.getCity()).isEqualTo("London"); assertThat(bean.metaBean().beanType()).isEqualTo(ReflectiveMutable.class); assertThat(bean.metaBean().metaPropertyCount()).isEqualTo(4); assertThat(bean.metaBean().metaPropertyExists("number")).isTrue(); assertThat(bean.metaBean().metaPropertyExists("foobar")).isFalse(); MetaProperty mp = bean.metaBean().metaProperty("number"); assertThat(mp.propertyType()).isEqualTo(int.class); assertThat(mp.declaringType()).isEqualTo(ReflectiveMutable.class); assertThat(mp.get(bean)).isEqualTo(12); assertThat(mp.style()).isEqualTo(PropertyStyle.READ_WRITE); MetaProperty mp2 = bean.metaBean().metaProperty("street"); assertThat(mp2.propertyType()).isEqualTo(String.class); assertThat(mp2.propertyGenericType()).isEqualTo(String.class); assertThat(mp2.declaringType()).isEqualTo(ReflectiveMutable.class); assertThat(mp2.get(bean)).isEqualTo("Park Lane"); assertThat(mp2.style()).isEqualTo(PropertyStyle.READ_WRITE); assertThat(JodaBeanSer.PRETTY.xmlWriter().write(bean)).contains("Park Lane<"); } } ================================================ FILE: src/test/java/org/joda/beans/TestResolvedType.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import java.io.Serializable; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import org.joda.beans.sample.AbstractResult; import org.joda.beans.sample.Address; import org.joda.beans.sample.AddressResult; import org.joda.beans.sample.CompanyAddress; import org.joda.beans.sample.CompanyAddressMidResult; import org.joda.beans.sample.CompanyAddressResult; import org.joda.beans.sample.DoubleGenericsNoExtendsNoSuper; import org.joda.beans.sample.DoubleGenericsWithExtendsNoSuper; import org.joda.beans.sample.GenericArray; import org.joda.beans.sample.GenericInterfaceBase; import org.joda.beans.sample.GenericInterfaceChild; import org.joda.beans.sample.GenericInterfaceImpl; import org.joda.beans.sample.GenericInterfaceMid; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmArrays; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.MidAbstractResult; import org.joda.beans.sample.Person; import org.joda.beans.sample.RiskLevel; import org.joda.beans.sample.SubDecimal; import org.joda.convert.StringConvert; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; /** * Test {@link ResolvedType}. */ class TestResolvedType { private static final Predicate HIDDEN_CLASS_PREDICATE = String::isEmpty; static Object[][] data_resolvedTypes() { return new Object[][] { {ResolvedType.of(String.class), String.class, List.of(), "String"}, {ResolvedType.of(List.class), List.class, List.of(), "List"}, {ResolvedType.from(String.class), String.class, List.of(), "String"}, {ResolvedType.from(List.class), List.class, List.of(ResolvedType.OBJECT), "List"}, {ResolvedType.ofFlat(String.class), String.class, List.of(), "String"}, {ResolvedType.ofFlat(List.class, String.class), List.class, List.of(ResolvedType.of(String.class)), "List"}, {ResolvedType.ofFlat(List.class, int.class), List.class, List.of(ResolvedType.of(int.class)), "List"}, {ResolvedType.of(List.class, ResolvedType.STRING), List.class, List.of(ResolvedType.of(String.class)), "List"}, {ResolvedType.ofFlat(Map.class, String.class, Number.class), Map.class, List.of(ResolvedType.of(String.class), ResolvedType.of(Number.class)), "Map"}, {ResolvedType.of(String[].class), String[].class, List.of(), "String[]"}, {ResolvedType.of(List[].class), List[].class, List.of(), "List[]"}, {ResolvedType.ofFlat(List[].class, String.class), List[].class, List.of(ResolvedType.of(String.class)), "List[]"}, {ResolvedType.of(String[][].class), String[][].class, List.of(), "String[][]"}, {ResolvedType.ofFlat(List[][].class, String.class), List[][].class, List.of(ResolvedType.of(String.class)), "List[][]"}, {ResolvedType.from(List[][].class), List[][].class, List.of(ResolvedType.of(Object.class)), "List[][]"}, {ResolvedType.ofFlat(Map[].class, String.class, List[].class), Map[].class, List.of(ResolvedType.STRING, ResolvedType.of(List[].class)), "Map[]"}, {ResolvedType.of(Map[].class, ResolvedType.STRING, ResolvedType.ofFlat(List[].class, Number.class)), Map[].class, List.of(ResolvedType.STRING, ResolvedType.of(List[].class, ResolvedType.of(Number.class))), "Map[]>[]"}, {ResolvedType.from(Person.meta().addressList().propertyGenericType(), Person.class), List.class, List.of(ResolvedType.of(Address.class)), "List"}, {ResolvedType.from(Person.meta().addressesList().propertyGenericType(), Person.class), List.class, List.of(ResolvedType.ofFlat(List.class, Address.class)), "List>"}, {ResolvedType.from(ImmPerson.meta().codeCounts().propertyGenericType(), ImmPerson.class), ImmutableMultiset.class, List.of(ResolvedType.of(String.class)), "com.google.common.collect.ImmutableMultiset"}, {ResolvedType.from(ImmAddress.meta().listNumericInMap().propertyGenericType(), ImmAddress.class), ImmutableMap.class, List.of(ResolvedType.of(String.class), ResolvedType.ofFlat(List.class, Integer.class)), "com.google.common.collect.ImmutableMap>"}, {ResolvedType.from(ImmGuava.meta().mapWildKey().propertyGenericType(), ImmGuava.class), ImmutableMap.class, List.of(ResolvedType.of(Number.class), ResolvedType.of(String.class)), "com.google.common.collect.ImmutableMap"}, {ResolvedType.from(ImmGuava.meta().listWildExtendsComparable().propertyGenericType(), ImmGuava.class), ImmutableList.class, List.of(ResolvedType.ofFlat(Comparable.class, Object.class)), "com.google.common.collect.ImmutableList>"}, {ResolvedType.from(ImmGuava.meta().listWildExtendsT().propertyGenericType(), ImmGuava.class), ImmutableList.class, List.of(ResolvedType.of(Comparable.class, ResolvedType.of(Object.class))), "com.google.common.collect.ImmutableList>"}, {ResolvedType.from(AddressResult.meta().docs().propertyGenericType(), AddressResult.class), List.class, List.of(ResolvedType.of(Address.class)), "List"}, {ResolvedType.from(AddressResult.meta().docs().propertyGenericType(), CompanyAddressResult.class), List.class, List.of(ResolvedType.of(CompanyAddress.class)), "List"}, {ResolvedType.from(AddressResult.meta().docs().propertyGenericType(), MidAbstractResult.class), List.class, List.of(ResolvedType.of(Address.class)), "List"}, {ResolvedType.from(AddressResult.meta().docs().propertyGenericType(), CompanyAddressMidResult.class), List.class, List.of(ResolvedType.of(CompanyAddress.class)), "List"}, {ResolvedType.from(ImmArrays.meta().intArray().propertyGenericType(), ImmArrays.class), int[].class, List.of(), "int[]"}, {ResolvedType.from(GenericArray.meta().values().propertyGenericType(), GenericArray.class), Address[].class, List.of(), "org.joda.beans.sample.Address[]"}, {ResolvedType.from( DoubleGenericsNoExtendsNoSuper.meta().typeTArray().propertyGenericType(), DoubleGenericsNoExtendsNoSuper.class), Object[].class, List.of(), "Object[]"}, {ResolvedType.from( DoubleGenericsWithExtendsNoSuper.meta().typeTArray().propertyGenericType(), DoubleGenericsWithExtendsNoSuper.class), Serializable[].class, List.of(), "java.io.Serializable[]"}, {ResolvedType.from( DoubleGenericsWithExtendsNoSuper.meta().typeTArrayOfList().propertyGenericType(), DoubleGenericsWithExtendsNoSuper.class), List[].class, List.of(ResolvedType.of(Serializable.class)), "List[]"}, {ResolvedType.from( DoubleGenericsWithExtendsNoSuper.meta().typeTArray2dOfList().propertyGenericType(), DoubleGenericsWithExtendsNoSuper.class), List[][].class, List.of(ResolvedType.of(Serializable.class)), "List[][]"}, {ResolvedType.from(GenericInterfaceBase.class.getMethods()[0].getGenericReturnType(), GenericInterfaceBase.class), List.class, List.of(ResolvedType.of(Serializable.class)), "List"}, {ResolvedType.from(GenericInterfaceBase.class.getMethods()[0].getGenericReturnType(), GenericInterfaceChild.class), List.class, List.of(ResolvedType.of(Number.class)), "List"}, {ResolvedType.from(GenericInterfaceBase.class.getMethods()[0].getGenericReturnType(), GenericInterfaceMid.class), List.class, List.of(ResolvedType.of(BigDecimal.class)), "List"}, {ResolvedType.from(GenericInterfaceBase.class.getMethods()[0].getGenericReturnType(), GenericInterfaceImpl.class), List.class, List.of(ResolvedType.of(SubDecimal.class)), "List"}, {ResolvedType.from(List.class, Object.class), List.class, List.of(ResolvedType.of(Object.class)), "List"}, {ResolvedType.from(List.class, Object.class), List.class, List.of(ResolvedType.of(Object.class)), "List"}, {ResolvedType.from(AbstractResult.class, AbstractResult.class), AbstractResult.class, List.of(ResolvedType.of(Address.class)), "org.joda.beans.sample.AbstractResult"}, {ResolvedType.from(AbstractResult.class, CompanyAddressResult.class), AbstractResult.class, List.of(ResolvedType.of(CompanyAddress.class)), "org.joda.beans.sample.AbstractResult"}, // recursive generics {ResolvedType.of(Enum.class), Enum.class, List.of(), "java.lang.Enum"}, {ResolvedType.from(Enum.class), Enum.class, List.of(ResolvedType.ofFlat(Enum.class, Object.class)), "java.lang.Enum>"}, {ResolvedType.from(Enum.class, Thread.State.class), // also test nested classes Enum.class, List.of(ResolvedType.of(Thread.State.class)), "java.lang.Enum"}, // enums with class-per-constant {ResolvedType.from(Enum.class, RiskLevel.class), Enum.class, List.of(ResolvedType.of(RiskLevel.class)), "java.lang.Enum"}, {ResolvedType.from(Enum.class, RiskLevel.HIGH.getClass()), Enum.class, List.of(ResolvedType.of(RiskLevel.class)), "java.lang.Enum"}, }; } @ParameterizedTest @MethodSource("data_resolvedTypes") void test_basics( ResolvedType test, Class expectedRawType, List expectedArgTypes, String expectedToString) { assertThat(test.getRawType()).isEqualTo(expectedRawType); assertThat(test.getArguments()).containsExactlyElementsOf(expectedArgTypes); assertThat(test).hasToString(expectedToString); assertThat(test).hasSameHashCodeAs(test); assertThat(test.equals(test)).isTrue(); assertThat(test.equals(new Object())).isFalse(); assertThat(test.equals(ResolvedType.of(TestResolvedType.class))).isFalse(); assertThat(test.equals(ResolvedType.ofFlat(List.class, TestResolvedType.class))).isFalse(); } @ParameterizedTest @MethodSource("data_resolvedTypes") void test_queries( ResolvedType test, Class expectedRawType, List expectedArgTypes, String expectedToString) { var expectedRawTypeWithoutArray = expectedRawType; if (expectedRawTypeWithoutArray.isArray()) { expectedRawTypeWithoutArray = expectedRawTypeWithoutArray.getComponentType(); if (expectedRawTypeWithoutArray.isArray()) { expectedRawTypeWithoutArray = expectedRawTypeWithoutArray.getComponentType(); } } if (expectedArgTypes.isEmpty()) { assertThat(test.getArgumentOrDefault(0)).isEqualTo(ResolvedType.OBJECT); assertThat(test.isRaw()).isEqualTo(expectedRawTypeWithoutArray.getTypeParameters().length != 0); } else if (expectedArgTypes.size() == 1) { assertThat(test.getArgumentOrDefault(0)).isEqualTo(expectedArgTypes.get(0)); assertThat(test.getArgumentOrDefault(1)).isEqualTo(ResolvedType.OBJECT); assertThat(test.isRaw()).isFalse(); } else if (expectedArgTypes.size() == 2) { assertThat(test.getArgumentOrDefault(0)).isEqualTo(expectedArgTypes.get(0)); assertThat(test.getArgumentOrDefault(1)).isEqualTo(expectedArgTypes.get(1)); assertThat(test.getArgumentOrDefault(2)).isEqualTo(ResolvedType.OBJECT); assertThat(test.isRaw()).isFalse(); } if (expectedRawType.isArray()) { assertThat(test.isArray()).isTrue(); assertThat(test.toComponentType()) .isEqualTo(ResolvedType.of(expectedRawType.getComponentType(), test.getArguments().toArray(new ResolvedType[0]))); } else { assertThat(test.isArray()).isFalse(); assertThat(test.toComponentType()).isEqualTo(test); } assertThat(test.toArrayType().toComponentType()).isEqualTo(test); assertThat(test.toBaseComponentType().getRawType()).isEqualTo(expectedRawTypeWithoutArray); assertThat(test.toBaseComponentType().getArguments()).isEqualTo(test.getArguments()); assertThat(test.isPrimitive()).isEqualTo(expectedRawType.isPrimitive()); assertThat(test.isParameterized()).isEqualTo(expectedRawTypeWithoutArray.getTypeParameters().length > 0); } @ParameterizedTest @MethodSource("data_resolvedTypes") void test_javaType( ResolvedType test, Class expectedRawType, List expectedArgTypes, String expectedToString) { if (test.getArguments().isEmpty()) { assertThat(test.toJavaType()).isEqualTo(expectedRawType); } assertThat(ResolvedType.fromAllowRaw(test.toJavaType(), Object.class)).isEqualTo(test); } @ParameterizedTest @MethodSource("data_resolvedTypes") void test_jodaConvert( ResolvedType test, Class expectedRawType, List expectedArgTypes, String expectedToString) { var str = StringConvert.INSTANCE.convertToString(test); assertThat(str).isEqualTo(expectedToString); var obj = StringConvert.INSTANCE.convertFromString(ResolvedType.class, str); assertThat(obj).isEqualTo(test); } @Test void test_hidden() { var test = ResolvedType.of(HIDDEN_CLASS_PREDICATE.getClass()); assertThat(test.isArray()).isFalse(); assertThat(test.isParameterized()).isFalse(); assertThat(test.isPrimitive()).isFalse(); assertThat(test.isRaw()).isFalse(); assertThat(test.getRawType()).isSameAs(HIDDEN_CLASS_PREDICATE.getClass()); assertThat(test.getArguments()).isEmpty(); assertThat(test.toString()).isEqualTo(HIDDEN_CLASS_PREDICATE.getClass().getName()); assertThat(test.toJavaType()).isEqualTo(HIDDEN_CLASS_PREDICATE.getClass()); } //------------------------------------------------------------------------- static Object[][] data_boxed() { return new Object[][] { {String.class, String.class}, {long.class, Long.class}, {int.class, Integer.class}, {short.class, Short.class}, {byte.class, Byte.class}, {double.class, Double.class}, {float.class, Float.class}, {char.class, Character.class}, {boolean.class, Boolean.class}, {void.class, Void.class}, }; } @ParameterizedTest @MethodSource("data_boxed") void test_boxed(Class primitive, Class box) { var test = ResolvedType.of(primitive); assertThat(test.isPrimitive()).isEqualTo(primitive != String.class); assertThat(test.toBoxed()).isEqualTo(ResolvedType.of(box)); } //------------------------------------------------------------------------- static Object[][] data_invalidParse() { return new Object[][] { {"String,"}, {"String<"}, {"String>"}, {"String]"}, {"String[]]"}, {"List<>"}, {"List<String"}, {"List<"}, {"List>"}, {"List[]<"}, {"List"}, {"List[]String"}, {"ListString"}, }; } @ParameterizedTest @MethodSource("data_invalidParse") void test_invalidParse(String stringToParse) { assertThatIllegalArgumentException() .isThrownBy(() -> ResolvedType.parse(stringToParse)) .withMessageMatching( "Unable to parse ResolvedType( from '" + Pattern.quote(stringToParse) + "', invalid format|, class not found: .*)"); } @Test void test_enumSubclass() { var test = ResolvedType.of(RiskLevel.HIGH.getClass()); assertThat(test.getRawType().getSuperclass()).isEqualTo(RiskLevel.class); } @SuppressWarnings("unused") private final List field1 = null; @SuppressWarnings("unused") private final Map> field2 = null; @SuppressWarnings("unused") private final Map[]>[][] field3 = null; @SuppressWarnings("unused") private final Optional field0 = null; @SuppressWarnings("unused") private final List field1b = null; @SuppressWarnings("unused") private final Map[]>[][] field3b = null; //------------------------------------------------------------------------- static Object[][] data_dynamicTypes() throws Exception { return new Object[][] { {String.class}, {String[].class}, {List[].class}, {List[][].class}, {TestResolvedType.class.getDeclaredField("field1").getGenericType()}, {TestResolvedType.class.getDeclaredField("field2").getGenericType()}, {TestResolvedType.class.getDeclaredField("field3").getGenericType()}, }; } @ParameterizedTest @MethodSource("data_dynamicTypes") void test_dynamicTypes(Type type) throws Exception { var test = ResolvedType.fromAllowRaw(type, Object.class); assertThat(test.toJavaType()) .isEqualTo(type) .isNotEqualTo("") .isNotEqualTo(Object.class) .isNotEqualTo(TestResolvedType.class.getDeclaredField("field0").getGenericType()) .isNotEqualTo(TestResolvedType.class.getDeclaredField("field1b").getGenericType()) .isNotEqualTo(TestResolvedType.class.getDeclaredField("field3b").getGenericType()); assertThat(test.toJavaType().toString()).isEqualTo(type.toString()); } } ================================================ FILE: src/test/java/org/joda/beans/TestResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.List; import java.util.NoSuchElementException; import org.joda.beans.sample.AbstractResult; import org.joda.beans.sample.Address; import org.joda.beans.sample.AddressResult; import org.joda.beans.sample.CompanyAddress; import org.joda.beans.sample.CompanyAddressMidResult; import org.joda.beans.sample.CompanyAddressResult; import org.junit.jupiter.api.Test; /** * Test property using Person. */ class TestResult { @Test void test_bean() { Bean test = new AddressResult(); assertThat(test.metaBean()).isEqualTo(AddressResult.meta()); assertThat(test.propertyNames().contains("docs")).isTrue(); assertThat(test.property("docs").name()).isEqualTo("docs"); assertThat(test.toString()).isEqualTo("AddressResult{docs=null, resultType=Address}"); } @Test void test_bean_invalidPropertyName() { Bean test = AddressResult.meta().builder().build(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.property("Rubbish")); } //----------------------------------------------------------------------- @Test void test_metaBean() { MetaBean test = AddressResult.meta(); assertThat(test.beanType()).isEqualTo(AddressResult.class); assertThat(test.beanName()).isEqualTo(AddressResult.class.getName()); assertThat(test.metaPropertyCount()).isEqualTo(2); assertThat(test.metaPropertyExists("docs")).isTrue(); assertThat(test.metaProperty("docs").name()).isEqualTo("docs"); assertThat(test.metaPropertyExists("resultType")).isTrue(); assertThat(test.metaProperty("resultType").name()).isEqualTo("resultType"); } @Test void test_metaBean_invalidPropertyName() { MetaBean test = AddressResult.meta(); assertThatExceptionOfType(NoSuchElementException.class) .isThrownBy(() -> test.metaProperty("Rubbish")); } //----------------------------------------------------------------------- @Test void test_genericType_abstract() { @SuppressWarnings("unchecked") AbstractResult.Meta
test = AbstractResult.meta(); assertThat(test.docs().propertyType()).isEqualTo(List.class); assertThat(JodaBeanUtils.collectionType(test.docs(), AbstractResult.class)).isEqualTo(Address.class); } @Test void test_genericType_Address() { AddressResult obj = new AddressResult(); AddressResult.Meta test = AddressResult.meta(); assertThat(test.docs().propertyType()).isEqualTo(List.class); assertThat(JodaBeanUtils.collectionType(obj.docs())).isEqualTo(Address.class); assertThat(JodaBeanUtils.collectionType(test.docs(), AddressResult.class)).isEqualTo(Address.class); } @Test void test_genericType_CompanyAddress() { CompanyAddressResult obj = new CompanyAddressResult(); CompanyAddressResult.Meta test = CompanyAddressResult.meta(); assertThat(test.docs().propertyType()).isEqualTo(List.class); assertThat(JodaBeanUtils.collectionType(obj.docs())).isEqualTo(CompanyAddress.class); assertThat(JodaBeanUtils.collectionType(test.docs(), test.docs().declaringType())).isEqualTo(Address.class); assertThat(JodaBeanUtils.collectionType(test.docs(), CompanyAddressResult.class)).isEqualTo(CompanyAddress.class); } @Test void test_genericType_CompanyAddressMid() { CompanyAddressMidResult obj = new CompanyAddressMidResult(); CompanyAddressMidResult.Meta test = CompanyAddressMidResult.meta(); assertThat(test.docs().propertyType()).isEqualTo(List.class); assertThat(JodaBeanUtils.collectionType(obj.docs())).isEqualTo(CompanyAddress.class); assertThat(JodaBeanUtils.collectionType(test.docs(), test.docs().declaringType())).isEqualTo(Address.class); assertThat(JodaBeanUtils.collectionType(test.docs(), CompanyAddressResult.class)).isEqualTo(CompanyAddress.class); } } ================================================ FILE: src/test/java/org/joda/beans/TestSubBean.java ================================================ /* * Copyright 2017-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.sample.ImmSubPersonNonFinal; import org.junit.jupiter.api.Test; /** * Test beans extending other beans. */ class TestSubBean { @Test void test_subbean_toBuilder() { // This sequence needs to be split like this as forename and surname returns ImmPersonNonFinal.Builder // instead of ImmSubPersonNonFinal.Builder ImmSubPersonNonFinal.Builder builder = ImmSubPersonNonFinal.builder(); builder .middleName("K.") .forename("John") .surname("Doe"); ImmSubPersonNonFinal person = builder.build(); ImmSubPersonNonFinal rebuilt = person.toBuilder().build(); assertThat(rebuilt).isEqualTo(person); } } ================================================ FILE: src/test/java/org/joda/beans/TestValidateBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import org.joda.beans.sample.SubValidateBean; import org.joda.beans.sample.ValidateBean; import org.junit.jupiter.api.Test; /** * Test ValidateBean. */ class TestValidateBean { @Test void test_notNull_set() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setFirst(null)); } @Test void test_notNull_propertySet() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.first().set(null)); } @Test void test_notNull_create() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder() .set("first", null) .set("second", "B") .set("third", "C") .set("fourth", "D") .build()); } @Test void test_notNull_create_notIncluded() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder().set("second", "B").set("third", "C").set("fourth", "D").build()); } //----------------------------------------------------------------------- @Test void test_notBlank_set_null() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setFifth(null)); } @Test void test_notBlank_set_empty() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setFifth(" ")); } @Test void test_notBlank_propertySet_null() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.fifth().set(null)); } @Test void test_notBlank_propertySet_empty() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.fifth().set(" ")); } //----------------------------------------------------------------------- @Test void test_notEmpty_set_null() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setSecond(null)); } @Test void test_notEmpty_set_empty() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setSecond("")); } @Test void test_notEmpty_propertySet_null() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.second().set(null)); } @Test void test_notEmpty_propertySet_empty() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.second().set("")); } @Test void test_notEmpty_create_null() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder() .set("first", "A") .set("second", null) .set("third", "C") .set("fourth", "D").build()); } @Test void test_notEmpty_create_empty() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder() .set("first", "A") .set("second", "") .set("third", "C") .set("fourth", "D") .build()); } @Test void test_notEmpty_create_notIncluded() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder() .set("first", "A") .set("third", "C") .set("fourth", "D") .build()); } //----------------------------------------------------------------------- @Test void test_static_set() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setThird(null)); } @Test void test_static_propertySet() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.third().set(null)); } @Test void test_static_create() { assertThatIllegalArgumentException() .isThrownBy( () -> ValidateBean.meta().builder() .set("first", "A") .set("second", "B") .set("third", "NotC") .set("fourth", "D") .build()) .withMessage("third"); } @Test void test_static_create_notIncluded() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder().set("first", "A").set("second", "B").set("fourth", "D").build()); } //----------------------------------------------------------------------- @Test void test_bean_set() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.setFourth(null)); } @Test void test_bean_propertySet() { ValidateBean test = new ValidateBean(); assertThatIllegalArgumentException() .isThrownBy(() -> test.fourth().set(null)); } @Test void test_bean_create() { assertThatIllegalArgumentException() .isThrownBy(() -> ValidateBean.meta().builder() .set("first", "A") .set("second", "B") .set("third", "C") .set("fourth", "NotD") .build()) .withMessage("fourth"); } @Test void test_bean_create_notIncluded() { assertThatIllegalArgumentException().isThrownBy( () -> ValidateBean.meta().builder().set("first", "A").set("second", "B").set("third", "C").build()); } //----------------------------------------------------------------------- @Test void test_subbean_create_notIncluded() { assertThatIllegalArgumentException() .isThrownBy(() -> SubValidateBean.meta().builder() .set("first", "A") .set("second", "B") .set("third", "C") .set("fourth", "D") .build()) .withMessageContaining("sub"); } } ================================================ FILE: src/test/java/org/joda/beans/sample/AbstractResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public abstract class AbstractResult extends DirectBean { /** The docs. */ @PropertyDefinition private List docs; @DerivedProperty public abstract String getResultType(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code AbstractResult}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static AbstractResult.Meta meta() { return AbstractResult.Meta.INSTANCE; } /** * The meta-bean for {@code AbstractResult}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static AbstractResult.Meta metaAbstractResult(Class cls) { return AbstractResult.Meta.INSTANCE; } static { MetaBean.register(AbstractResult.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public AbstractResult.Meta metaBean() { return AbstractResult.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the docs. * @return the value of the property */ public List getDocs() { return docs; } /** * Sets the docs. * @param docs the new value of the property */ public void setDocs(List docs) { this.docs = docs; } /** * Gets the the {@code docs} property. * @return the property, not null */ public final Property> docs() { return metaBean().docs().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the the {@code resultType} property. * @return the property, not null */ public final Property resultType() { return metaBean().resultType().createProperty(this); } //----------------------------------------------------------------------- @Override public AbstractResult clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { AbstractResult other = (AbstractResult) obj; return JodaBeanUtils.equal(this.getDocs(), other.getDocs()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getDocs()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("AbstractResult{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("docs").append('=').append(JodaBeanUtils.toString(getDocs())).append(',').append(' '); buf.append("resultType").append('=').append(JodaBeanUtils.toString(getResultType())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code AbstractResult}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code docs} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> docs = DirectMetaProperty.ofReadWrite( this, "docs", AbstractResult.class, (Class) List.class); /** * The meta-property for the {@code resultType} property. */ private final MetaProperty resultType = DirectMetaProperty.ofDerived( this, "resultType", AbstractResult.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "docs", "resultType"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3088955: // docs return this.docs; case -571837193: // resultType return this.resultType; } return super.metaPropertyGet(propertyName); } @Override public boolean isBuildable() { return false; } @Override public BeanBuilder> builder() { throw new UnsupportedOperationException("AbstractResult is an abstract class"); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) AbstractResult.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code docs} property. * @return the meta-property, not null */ public final MetaProperty> docs() { return docs; } /** * The meta-property for the {@code resultType} property. * @return the meta-property, not null */ public final MetaProperty resultType() { return resultType; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3088955: // docs return ((AbstractResult) bean).getDocs(); case -571837193: // resultType return ((AbstractResult) bean).getResultType(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3088955: // docs ((AbstractResult) bean).setDocs((List) newValue); return; case -571837193: // resultType if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: resultType"); } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/Address.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class Address extends DirectBean { /** * The number. * This will be the flat, house number or house name. */ @PropertyDefinition private int number; // various empty comments for testing /** * */ @PropertyDefinition private String street; /** */ @PropertyDefinition private String city; /** */ @PropertyDefinition private Person owner; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code Address}. * @return the meta-bean, not null */ public static Address.Meta meta() { return Address.Meta.INSTANCE; } static { MetaBean.register(Address.Meta.INSTANCE); } @Override public Address.Meta metaBean() { return Address.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the number. * This will be the flat, house number or house name. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * This will be the flat, house number or house name. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } /** * Gets the the {@code number} property. * This will be the flat, house number or house name. * @return the property, not null */ public final Property number() { return metaBean().number().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the street. * @return the value of the property */ public String getStreet() { return street; } /** * Sets the street. * @param street the new value of the property */ public void setStreet(String street) { this.street = street; } /** * Gets the the {@code street} property. * @return the property, not null */ public final Property street() { return metaBean().street().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property */ public String getCity() { return city; } /** * Sets the city. * @param city the new value of the property */ public void setCity(String city) { this.city = city; } /** * Gets the the {@code city} property. * @return the property, not null */ public final Property city() { return metaBean().city().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property */ public Person getOwner() { return owner; } /** * Sets the owner. * @param owner the new value of the property */ public void setOwner(Person owner) { this.owner = owner; } /** * Gets the the {@code owner} property. * @return the property, not null */ public final Property owner() { return metaBean().owner().createProperty(this); } //----------------------------------------------------------------------- @Override public Address clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Address other = (Address) obj; return (this.getNumber() == other.getNumber()) && JodaBeanUtils.equal(this.getStreet(), other.getStreet()) && JodaBeanUtils.equal(this.getCity(), other.getCity()) && JodaBeanUtils.equal(this.getOwner(), other.getOwner()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(getStreet()); hash = hash * 31 + JodaBeanUtils.hashCode(getCity()); hash = hash * 31 + JodaBeanUtils.hashCode(getOwner()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("Address{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(getStreet())).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(getCity())).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(getOwner())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Address}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code number} property. */ private final MetaProperty number = DirectMetaProperty.ofReadWrite( this, "number", Address.class, Integer.TYPE); /** * The meta-property for the {@code street} property. */ private final MetaProperty street = DirectMetaProperty.ofReadWrite( this, "street", Address.class, String.class); /** * The meta-property for the {@code city} property. */ private final MetaProperty city = DirectMetaProperty.ofReadWrite( this, "city", Address.class, String.class); /** * The meta-property for the {@code owner} property. */ private final MetaProperty owner = DirectMetaProperty.ofReadWrite( this, "owner", Address.class, Person.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "number", "street", "city", "owner"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 106164915: // owner return this.owner; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new Address()); } @Override public Class beanType() { return Address.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code number} property. * @return the meta-property, not null */ public final MetaProperty number() { return number; } /** * The meta-property for the {@code street} property. * @return the meta-property, not null */ public final MetaProperty street() { return street; } /** * The meta-property for the {@code city} property. * @return the meta-property, not null */ public final MetaProperty city() { return city; } /** * The meta-property for the {@code owner} property. * @return the meta-property, not null */ public final MetaProperty owner() { return owner; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1034364087: // number return ((Address) bean).getNumber(); case -891990013: // street return ((Address) bean).getStreet(); case 3053931: // city return ((Address) bean).getCity(); case 106164915: // owner return ((Address) bean).getOwner(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1034364087: // number ((Address) bean).setNumber((Integer) newValue); return; case -891990013: // street ((Address) bean).setStreet((String) newValue); return; case 3053931: // city ((Address) bean).setCity((String) newValue); return; case 106164915: // owner ((Address) bean).setOwner((Person) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/AddressResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class AddressResult extends AbstractResult
{ @Override public String getResultType() { return "Address"; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code AddressResult}. * @return the meta-bean, not null */ public static AddressResult.Meta meta() { return AddressResult.Meta.INSTANCE; } static { MetaBean.register(AddressResult.Meta.INSTANCE); } @Override public AddressResult.Meta metaBean() { return AddressResult.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public AddressResult clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("AddressResult{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } //----------------------------------------------------------------------- /** * The meta-bean for {@code AddressResult}. */ public static class Meta extends AbstractResult.Meta
{ /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap()); /** * Restricted constructor. */ protected Meta() { } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new AddressResult()); } @Override public Class beanType() { return AddressResult.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ClassAnnotation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Used to test annotations. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ClassAnnotation { Class value(); } ================================================ FILE: src/test/java/org/joda/beans/sample/ClonePerson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class ClonePerson implements Bean { @PropertyDefinition private List firstNames; @PropertyDefinition private String[] middleNames; @PropertyDefinition private String surname; @PropertyDefinition(validate = "notNull") private Date dateOfBirth; @PropertyDefinition private Date dateOfDeath; @PropertyDefinition private final List
addresses = new ArrayList<>(); @PropertyDefinition private Company[] companies; @PropertyDefinition private int[] amounts; /** * Creates an instance. */ public ClonePerson() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ClonePerson}. * @return the meta-bean, not null */ public static ClonePerson.Meta meta() { return ClonePerson.Meta.INSTANCE; } static { MetaBean.register(ClonePerson.Meta.INSTANCE); } @Override public ClonePerson.Meta metaBean() { return ClonePerson.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the firstNames. * @return the value of the property */ public List getFirstNames() { return firstNames; } /** * Sets the firstNames. * @param firstNames the new value of the property */ public void setFirstNames(List firstNames) { this.firstNames = firstNames; } /** * Gets the the {@code firstNames} property. * @return the property, not null */ public final Property> firstNames() { return metaBean().firstNames().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the middleNames. * @return the value of the property */ public String[] getMiddleNames() { return middleNames; } /** * Sets the middleNames. * @param middleNames the new value of the property */ public void setMiddleNames(String[] middleNames) { this.middleNames = middleNames; } /** * Gets the the {@code middleNames} property. * @return the property, not null */ public final Property middleNames() { return metaBean().middleNames().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public String getSurname() { return surname; } /** * Sets the surname. * @param surname the new value of the property */ public void setSurname(String surname) { this.surname = surname; } /** * Gets the the {@code surname} property. * @return the property, not null */ public final Property surname() { return metaBean().surname().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the dateOfBirth. * @return the value of the property, not null */ public Date getDateOfBirth() { return dateOfBirth; } /** * Sets the dateOfBirth. * @param dateOfBirth the new value of the property, not null */ public void setDateOfBirth(Date dateOfBirth) { JodaBeanUtils.notNull(dateOfBirth, "dateOfBirth"); this.dateOfBirth = dateOfBirth; } /** * Gets the the {@code dateOfBirth} property. * @return the property, not null */ public final Property dateOfBirth() { return metaBean().dateOfBirth().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the dateOfDeath. * @return the value of the property */ public Date getDateOfDeath() { return dateOfDeath; } /** * Sets the dateOfDeath. * @param dateOfDeath the new value of the property */ public void setDateOfDeath(Date dateOfDeath) { this.dateOfDeath = dateOfDeath; } /** * Gets the the {@code dateOfDeath} property. * @return the property, not null */ public final Property dateOfDeath() { return metaBean().dateOfDeath().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addresses. * @return the value of the property, not null */ public List
getAddresses() { return addresses; } /** * Sets the addresses. * @param addresses the new value of the property, not null */ public void setAddresses(List
addresses) { JodaBeanUtils.notNull(addresses, "addresses"); this.addresses.clear(); this.addresses.addAll(addresses); } /** * Gets the the {@code addresses} property. * @return the property, not null */ public final Property> addresses() { return metaBean().addresses().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the companies. * @return the value of the property */ public Company[] getCompanies() { return companies; } /** * Sets the companies. * @param companies the new value of the property */ public void setCompanies(Company[] companies) { this.companies = companies; } /** * Gets the the {@code companies} property. * @return the property, not null */ public final Property companies() { return metaBean().companies().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the amounts. * @return the value of the property */ public int[] getAmounts() { return amounts; } /** * Sets the amounts. * @param amounts the new value of the property */ public void setAmounts(int[] amounts) { this.amounts = amounts; } /** * Gets the the {@code amounts} property. * @return the property, not null */ public final Property amounts() { return metaBean().amounts().createProperty(this); } //----------------------------------------------------------------------- @Override public ClonePerson clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ClonePerson other = (ClonePerson) obj; return JodaBeanUtils.equal(this.getFirstNames(), other.getFirstNames()) && JodaBeanUtils.equal(this.getMiddleNames(), other.getMiddleNames()) && JodaBeanUtils.equal(this.getSurname(), other.getSurname()) && JodaBeanUtils.equal(this.getDateOfBirth(), other.getDateOfBirth()) && JodaBeanUtils.equal(this.getDateOfDeath(), other.getDateOfDeath()) && JodaBeanUtils.equal(this.getAddresses(), other.getAddresses()) && JodaBeanUtils.equal(this.getCompanies(), other.getCompanies()) && JodaBeanUtils.equal(this.getAmounts(), other.getAmounts()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getFirstNames()); hash = hash * 31 + JodaBeanUtils.hashCode(getMiddleNames()); hash = hash * 31 + JodaBeanUtils.hashCode(getSurname()); hash = hash * 31 + JodaBeanUtils.hashCode(getDateOfBirth()); hash = hash * 31 + JodaBeanUtils.hashCode(getDateOfDeath()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddresses()); hash = hash * 31 + JodaBeanUtils.hashCode(getCompanies()); hash = hash * 31 + JodaBeanUtils.hashCode(getAmounts()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("ClonePerson{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("firstNames").append('=').append(JodaBeanUtils.toString(getFirstNames())).append(',').append(' '); buf.append("middleNames").append('=').append(JodaBeanUtils.toString(getMiddleNames())).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(getSurname())).append(',').append(' '); buf.append("dateOfBirth").append('=').append(JodaBeanUtils.toString(getDateOfBirth())).append(',').append(' '); buf.append("dateOfDeath").append('=').append(JodaBeanUtils.toString(getDateOfDeath())).append(',').append(' '); buf.append("addresses").append('=').append(JodaBeanUtils.toString(getAddresses())).append(',').append(' '); buf.append("companies").append('=').append(JodaBeanUtils.toString(getCompanies())).append(',').append(' '); buf.append("amounts").append('=').append(JodaBeanUtils.toString(getAmounts())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ClonePerson}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code firstNames} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> firstNames = DirectMetaProperty.ofReadWrite( this, "firstNames", ClonePerson.class, (Class) List.class); /** * The meta-property for the {@code middleNames} property. */ private final MetaProperty middleNames = DirectMetaProperty.ofReadWrite( this, "middleNames", ClonePerson.class, String[].class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofReadWrite( this, "surname", ClonePerson.class, String.class); /** * The meta-property for the {@code dateOfBirth} property. */ private final MetaProperty dateOfBirth = DirectMetaProperty.ofReadWrite( this, "dateOfBirth", ClonePerson.class, Date.class); /** * The meta-property for the {@code dateOfDeath} property. */ private final MetaProperty dateOfDeath = DirectMetaProperty.ofReadWrite( this, "dateOfDeath", ClonePerson.class, Date.class); /** * The meta-property for the {@code addresses} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addresses = DirectMetaProperty.ofReadWrite( this, "addresses", ClonePerson.class, (Class) List.class); /** * The meta-property for the {@code companies} property. */ private final MetaProperty companies = DirectMetaProperty.ofReadWrite( this, "companies", ClonePerson.class, Company[].class); /** * The meta-property for the {@code amounts} property. */ private final MetaProperty amounts = DirectMetaProperty.ofReadWrite( this, "amounts", ClonePerson.class, int[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "firstNames", "middleNames", "surname", "dateOfBirth", "dateOfDeath", "addresses", "companies", "amounts"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -177061256: // firstNames return this.firstNames; case 404996787: // middleNames return this.middleNames; case -1852993317: // surname return this.surname; case -386871910: // dateOfBirth return this.dateOfBirth; case -385160369: // dateOfDeath return this.dateOfDeath; case 874544034: // addresses return this.addresses; case -1412832805: // companies return this.companies; case -879772901: // amounts return this.amounts; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new ClonePerson()); } @Override public Class beanType() { return ClonePerson.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code firstNames} property. * @return the meta-property, not null */ public final MetaProperty> firstNames() { return firstNames; } /** * The meta-property for the {@code middleNames} property. * @return the meta-property, not null */ public final MetaProperty middleNames() { return middleNames; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public final MetaProperty surname() { return surname; } /** * The meta-property for the {@code dateOfBirth} property. * @return the meta-property, not null */ public final MetaProperty dateOfBirth() { return dateOfBirth; } /** * The meta-property for the {@code dateOfDeath} property. * @return the meta-property, not null */ public final MetaProperty dateOfDeath() { return dateOfDeath; } /** * The meta-property for the {@code addresses} property. * @return the meta-property, not null */ public final MetaProperty> addresses() { return addresses; } /** * The meta-property for the {@code companies} property. * @return the meta-property, not null */ public final MetaProperty companies() { return companies; } /** * The meta-property for the {@code amounts} property. * @return the meta-property, not null */ public final MetaProperty amounts() { return amounts; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -177061256: // firstNames return ((ClonePerson) bean).getFirstNames(); case 404996787: // middleNames return ((ClonePerson) bean).getMiddleNames(); case -1852993317: // surname return ((ClonePerson) bean).getSurname(); case -386871910: // dateOfBirth return ((ClonePerson) bean).getDateOfBirth(); case -385160369: // dateOfDeath return ((ClonePerson) bean).getDateOfDeath(); case 874544034: // addresses return ((ClonePerson) bean).getAddresses(); case -1412832805: // companies return ((ClonePerson) bean).getCompanies(); case -879772901: // amounts return ((ClonePerson) bean).getAmounts(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -177061256: // firstNames ((ClonePerson) bean).setFirstNames((List) newValue); return; case 404996787: // middleNames ((ClonePerson) bean).setMiddleNames((String[]) newValue); return; case -1852993317: // surname ((ClonePerson) bean).setSurname((String) newValue); return; case -386871910: // dateOfBirth ((ClonePerson) bean).setDateOfBirth((Date) newValue); return; case -385160369: // dateOfDeath ((ClonePerson) bean).setDateOfDeath((Date) newValue); return; case 874544034: // addresses ((ClonePerson) bean).setAddresses((List
) newValue); return; case -1412832805: // companies ((ClonePerson) bean).setCompanies((Company[]) newValue); return; case -879772901: // amounts ((ClonePerson) bean).setAmounts((int[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((ClonePerson) bean).dateOfBirth, "dateOfBirth"); JodaBeanUtils.notNull(((ClonePerson) bean).addresses, "addresses"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/Company.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class Company implements Bean { /** The company name. */ @PropertyDefinition private String companyName; /** * Creates an instanec. */ public Company() { } /** * Creates an instanec. * * @param name the name */ public Company(String name) { companyName = name; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code Company}. * @return the meta-bean, not null */ public static Company.Meta meta() { return Company.Meta.INSTANCE; } static { MetaBean.register(Company.Meta.INSTANCE); } @Override public Company.Meta metaBean() { return Company.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the company name. * @return the value of the property */ public String getCompanyName() { return companyName; } /** * Sets the company name. * @param companyName the new value of the property */ public void setCompanyName(String companyName) { this.companyName = companyName; } /** * Gets the the {@code companyName} property. * @return the property, not null */ public final Property companyName() { return metaBean().companyName().createProperty(this); } //----------------------------------------------------------------------- @Override public Company clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Company other = (Company) obj; return JodaBeanUtils.equal(this.getCompanyName(), other.getCompanyName()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getCompanyName()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("Company{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("companyName").append('=').append(JodaBeanUtils.toString(getCompanyName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Company}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code companyName} property. */ private final MetaProperty companyName = DirectMetaProperty.ofReadWrite( this, "companyName", Company.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "companyName"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -508582744: // companyName return this.companyName; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new Company()); } @Override public Class beanType() { return Company.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code companyName} property. * @return the meta-property, not null */ public final MetaProperty companyName() { return companyName; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -508582744: // companyName return ((Company) bean).getCompanyName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -508582744: // companyName ((Company) bean).setCompanyName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/CompanyAddress.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.beans.PropertyChangeSupport; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class CompanyAddress extends Address { /** The company name. */ @PropertyDefinition(set = "bound", equalsHashCodeStyle = "field", toStringStyle = "field") private String companyName; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code CompanyAddress}. * @return the meta-bean, not null */ public static CompanyAddress.Meta meta() { return CompanyAddress.Meta.INSTANCE; } static { MetaBean.register(CompanyAddress.Meta.INSTANCE); } /** * The property change support field. */ private final transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); @Override public CompanyAddress.Meta metaBean() { return CompanyAddress.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the company name. * @return the value of the property */ public String getCompanyName() { return companyName; } /** * Sets the company name. * @param companyName the new value of the property */ public void setCompanyName(String companyName) { String oldCompanyName = this.companyName; this.companyName = companyName; this.propertyChangeSupport.firePropertyChange("companyName", oldCompanyName, companyName); } /** * Gets the the {@code companyName} property. * @return the property, not null */ public final Property companyName() { return metaBean().companyName().createProperty(this); } //----------------------------------------------------------------------- @Override public CompanyAddress clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { CompanyAddress other = (CompanyAddress) obj; return JodaBeanUtils.equal(this.companyName, other.companyName) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(companyName); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("CompanyAddress{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("companyName").append('=').append(JodaBeanUtils.toString(companyName)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code CompanyAddress}. */ public static class Meta extends Address.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code companyName} property. */ private final MetaProperty companyName = DirectMetaProperty.ofReadWrite( this, "companyName", CompanyAddress.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "companyName"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -508582744: // companyName return this.companyName; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new CompanyAddress()); } @Override public Class beanType() { return CompanyAddress.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code companyName} property. * @return the meta-property, not null */ public final MetaProperty companyName() { return companyName; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -508582744: // companyName return ((CompanyAddress) bean).getCompanyName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -508582744: // companyName ((CompanyAddress) bean).setCompanyName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/CompanyAddressMidResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class CompanyAddressMidResult extends MidAbstractResult { @Override public String getResultType() { return "CompanyAddressMid"; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code CompanyAddressMidResult}. * @return the meta-bean, not null */ public static CompanyAddressMidResult.Meta meta() { return CompanyAddressMidResult.Meta.INSTANCE; } static { MetaBean.register(CompanyAddressMidResult.Meta.INSTANCE); } @Override public CompanyAddressMidResult.Meta metaBean() { return CompanyAddressMidResult.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public CompanyAddressMidResult clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("CompanyAddressMidResult{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } //----------------------------------------------------------------------- /** * The meta-bean for {@code CompanyAddressMidResult}. */ public static class Meta extends MidAbstractResult.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap()); /** * Restricted constructor. */ protected Meta() { } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new CompanyAddressMidResult()); } @Override public Class beanType() { return CompanyAddressMidResult.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/CompanyAddressResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class CompanyAddressResult extends AbstractResult { @Override public String getResultType() { return "CompanyAddress"; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code CompanyAddressResult}. * @return the meta-bean, not null */ public static CompanyAddressResult.Meta meta() { return CompanyAddressResult.Meta.INSTANCE; } static { MetaBean.register(CompanyAddressResult.Meta.INSTANCE); } @Override public CompanyAddressResult.Meta metaBean() { return CompanyAddressResult.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public CompanyAddressResult clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("CompanyAddressResult{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } //----------------------------------------------------------------------- /** * The meta-bean for {@code CompanyAddressResult}. */ public static class Meta extends AbstractResult.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap()); /** * Restricted constructor. */ protected Meta() { } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new CompanyAddressResult()); } @Override public Class beanType() { return CompanyAddressResult.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ComplexAnnotation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Used to test annotation parsing. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ComplexAnnotation { SimpleAnnotation[] value(); } ================================================ FILE: src/test/java/org/joda/beans/sample/Documentation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class Documentation extends DirectBean { /** The type. */ @PropertyDefinition private String type; /** The surname. */ @PropertyDefinition private T content; @PropertyDefinition private Map map; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code Documentation}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static Documentation.Meta meta() { return Documentation.Meta.INSTANCE; } /** * The meta-bean for {@code Documentation}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static Documentation.Meta metaDocumentation(Class cls) { return Documentation.Meta.INSTANCE; } static { MetaBean.register(Documentation.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public Documentation.Meta metaBean() { return Documentation.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the type. * @return the value of the property */ public String getType() { return type; } /** * Sets the type. * @param type the new value of the property */ public void setType(String type) { this.type = type; } /** * Gets the the {@code type} property. * @return the property, not null */ public final Property type() { return metaBean().type().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public T getContent() { return content; } /** * Sets the surname. * @param content the new value of the property */ public void setContent(T content) { this.content = content; } /** * Gets the the {@code content} property. * @return the property, not null */ public final Property content() { return metaBean().content().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the map. * @return the value of the property */ public Map getMap() { return map; } /** * Sets the map. * @param map the new value of the property */ public void setMap(Map map) { this.map = map; } /** * Gets the the {@code map} property. * @return the property, not null */ public final Property> map() { return metaBean().map().createProperty(this); } //----------------------------------------------------------------------- @Override public Documentation clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Documentation other = (Documentation) obj; return JodaBeanUtils.equal(this.getType(), other.getType()) && JodaBeanUtils.equal(this.getContent(), other.getContent()) && JodaBeanUtils.equal(this.getMap(), other.getMap()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getType()); hash = hash * 31 + JodaBeanUtils.hashCode(getContent()); hash = hash * 31 + JodaBeanUtils.hashCode(getMap()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("Documentation{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("type").append('=').append(JodaBeanUtils.toString(getType())).append(',').append(' '); buf.append("content").append('=').append(JodaBeanUtils.toString(getContent())).append(',').append(' '); buf.append("map").append('=').append(JodaBeanUtils.toString(getMap())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Documentation}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code type} property. */ private final MetaProperty type = DirectMetaProperty.ofReadWrite( this, "type", Documentation.class, String.class); /** * The meta-property for the {@code content} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty content = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "content", Documentation.class, Object.class); /** * The meta-property for the {@code map} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> map = DirectMetaProperty.ofReadWrite( this, "map", Documentation.class, (Class) Map.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "type", "content", "map"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3575610: // type return this.type; case 951530617: // content return this.content; case 107868: // map return this.map; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new Documentation()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) Documentation.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code type} property. * @return the meta-property, not null */ public final MetaProperty type() { return type; } /** * The meta-property for the {@code content} property. * @return the meta-property, not null */ public final MetaProperty content() { return content; } /** * The meta-property for the {@code map} property. * @return the meta-property, not null */ public final MetaProperty> map() { return map; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3575610: // type return ((Documentation) bean).getType(); case 951530617: // content return ((Documentation) bean).getContent(); case 107868: // map return ((Documentation) bean).getMap(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3575610: // type ((Documentation) bean).setType((String) newValue); return; case 951530617: // content ((Documentation) bean).setContent((T) newValue); return; case 107868: // map ((Documentation) bean).setMap((Map) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DocumentationHolder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * This tests a generic ? property. * * @author Stephen Colebourne */ @BeanDefinition public class DocumentationHolder extends DirectBean{ // NOTE: no space between DirectBean and { /** The documentation. */ @PropertyDefinition private Documentation documentation; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DocumentationHolder}. * @return the meta-bean, not null */ public static DocumentationHolder.Meta meta() { return DocumentationHolder.Meta.INSTANCE; } static { MetaBean.register(DocumentationHolder.Meta.INSTANCE); } @Override public DocumentationHolder.Meta metaBean() { return DocumentationHolder.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the documentation. * @return the value of the property */ public Documentation getDocumentation() { return documentation; } /** * Sets the documentation. * @param documentation the new value of the property */ public void setDocumentation(Documentation documentation) { this.documentation = documentation; } /** * Gets the the {@code documentation} property. * @return the property, not null */ public final Property> documentation() { return metaBean().documentation().createProperty(this); } //----------------------------------------------------------------------- @Override public DocumentationHolder clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DocumentationHolder other = (DocumentationHolder) obj; return JodaBeanUtils.equal(this.getDocumentation(), other.getDocumentation()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getDocumentation()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("DocumentationHolder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("documentation").append('=').append(JodaBeanUtils.toString(getDocumentation())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DocumentationHolder}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code documentation} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> documentation = DirectMetaProperty.ofReadWrite( this, "documentation", DocumentationHolder.class, (Class) Documentation.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "documentation"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1587405498: // documentation return this.documentation; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new DocumentationHolder()); } @Override public Class beanType() { return DocumentationHolder.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code documentation} property. * @return the meta-property, not null */ public final MetaProperty> documentation() { return documentation; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1587405498: // documentation return ((DocumentationHolder) bean).getDocumentation(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 1587405498: // documentation ((DocumentationHolder) bean).setDocumentation((Documentation) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsComplexExtendsSuperTwoGenerics.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsComplexExtendsSuperTwoGenerics, U extends Number> extends DoubleGenericsSimpleSuper { /** The normal type. */ @PropertyDefinition private String normalType; /** The type T value. */ @PropertyDefinition private T typeT; /** The type U value. */ @PropertyDefinition private U typeU; /** The type T value. */ @PropertyDefinition private List typeTList; /** The type U value. */ @PropertyDefinition private List typeUList; /** The type T value. */ @PropertyDefinition private T[] typeTArray; /** The type U value. */ @PropertyDefinition private U[] typeUArray; /** * Creates an instance. */ public DoubleGenericsComplexExtendsSuperTwoGenerics() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsComplexExtendsSuperTwoGenerics}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsComplexExtendsSuperTwoGenerics.Meta meta() { return DoubleGenericsComplexExtendsSuperTwoGenerics.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsComplexExtendsSuperTwoGenerics}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static , S extends Number> DoubleGenericsComplexExtendsSuperTwoGenerics.Meta metaDoubleGenericsComplexExtendsSuperTwoGenerics(Class cls1, Class cls2) { return DoubleGenericsComplexExtendsSuperTwoGenerics.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsComplexExtendsSuperTwoGenerics.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsComplexExtendsSuperTwoGenerics.Meta metaBean() { return DoubleGenericsComplexExtendsSuperTwoGenerics.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getNormalType() { return normalType; } /** * Sets the normal type. * @param normalType the new value of the property */ public void setNormalType(String normalType) { this.normalType = normalType; } /** * Gets the the {@code normalType} property. * @return the property, not null */ public final Property normalType() { return metaBean().normalType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getTypeT() { return typeT; } /** * Sets the type T value. * @param typeT the new value of the property */ public void setTypeT(T typeT) { this.typeT = typeT; } /** * Gets the the {@code typeT} property. * @return the property, not null */ public final Property typeT() { return metaBean().typeT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getTypeU() { return typeU; } /** * Sets the type U value. * @param typeU the new value of the property */ public void setTypeU(U typeU) { this.typeU = typeU; } /** * Gets the the {@code typeU} property. * @return the property, not null */ public final Property typeU() { return metaBean().typeU().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public List getTypeTList() { return typeTList; } /** * Sets the type T value. * @param typeTList the new value of the property */ public void setTypeTList(List typeTList) { this.typeTList = typeTList; } /** * Gets the the {@code typeTList} property. * @return the property, not null */ public final Property> typeTList() { return metaBean().typeTList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public List getTypeUList() { return typeUList; } /** * Sets the type U value. * @param typeUList the new value of the property */ public void setTypeUList(List typeUList) { this.typeUList = typeUList; } /** * Gets the the {@code typeUList} property. * @return the property, not null */ public final Property> typeUList() { return metaBean().typeUList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T[] getTypeTArray() { return typeTArray; } /** * Sets the type T value. * @param typeTArray the new value of the property */ public void setTypeTArray(T[] typeTArray) { this.typeTArray = typeTArray; } /** * Gets the the {@code typeTArray} property. * @return the property, not null */ public final Property typeTArray() { return metaBean().typeTArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U[] getTypeUArray() { return typeUArray; } /** * Sets the type U value. * @param typeUArray the new value of the property */ public void setTypeUArray(U[] typeUArray) { this.typeUArray = typeUArray; } /** * Gets the the {@code typeUArray} property. * @return the property, not null */ public final Property typeUArray() { return metaBean().typeUArray().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsComplexExtendsSuperTwoGenerics clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsComplexExtendsSuperTwoGenerics other = (DoubleGenericsComplexExtendsSuperTwoGenerics) obj; return JodaBeanUtils.equal(this.getNormalType(), other.getNormalType()) && JodaBeanUtils.equal(this.getTypeT(), other.getTypeT()) && JodaBeanUtils.equal(this.getTypeU(), other.getTypeU()) && JodaBeanUtils.equal(this.getTypeTList(), other.getTypeTList()) && JodaBeanUtils.equal(this.getTypeUList(), other.getTypeUList()) && JodaBeanUtils.equal(this.getTypeTArray(), other.getTypeTArray()) && JodaBeanUtils.equal(this.getTypeUArray(), other.getTypeUArray()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getNormalType()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeT()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeU()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUArray()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("DoubleGenericsComplexExtendsSuperTwoGenerics{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("normalType").append('=').append(JodaBeanUtils.toString(getNormalType())).append(',').append(' '); buf.append("typeT").append('=').append(JodaBeanUtils.toString(getTypeT())).append(',').append(' '); buf.append("typeU").append('=').append(JodaBeanUtils.toString(getTypeU())).append(',').append(' '); buf.append("typeTList").append('=').append(JodaBeanUtils.toString(getTypeTList())).append(',').append(' '); buf.append("typeUList").append('=').append(JodaBeanUtils.toString(getTypeUList())).append(',').append(' '); buf.append("typeTArray").append('=').append(JodaBeanUtils.toString(getTypeTArray())).append(',').append(' '); buf.append("typeUArray").append('=').append(JodaBeanUtils.toString(getTypeUArray())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsComplexExtendsSuperTwoGenerics}. * @param the type * @param the type */ public static class Meta, U extends Number> extends DoubleGenericsSimpleSuper.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code normalType} property. */ private final MetaProperty normalType = DirectMetaProperty.ofReadWrite( this, "normalType", DoubleGenericsComplexExtendsSuperTwoGenerics.class, String.class); /** * The meta-property for the {@code typeT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeT", DoubleGenericsComplexExtendsSuperTwoGenerics.class, Object.class); /** * The meta-property for the {@code typeU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeU", DoubleGenericsComplexExtendsSuperTwoGenerics.class, Object.class); /** * The meta-property for the {@code typeTList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeTList = DirectMetaProperty.ofReadWrite( this, "typeTList", DoubleGenericsComplexExtendsSuperTwoGenerics.class, (Class) List.class); /** * The meta-property for the {@code typeUList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeUList = DirectMetaProperty.ofReadWrite( this, "typeUList", DoubleGenericsComplexExtendsSuperTwoGenerics.class, (Class) List.class); /** * The meta-property for the {@code typeTArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeTArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeTArray", DoubleGenericsComplexExtendsSuperTwoGenerics.class, Object[].class); /** * The meta-property for the {@code typeUArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeUArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeUArray", DoubleGenericsComplexExtendsSuperTwoGenerics.class, Object[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "normalType", "typeT", "typeU", "typeTList", "typeUList", "typeTArray", "typeUArray"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1255672639: // normalType return this.normalType; case 110843994: // typeT return this.typeT; case 110843995: // typeU return this.typeU; case 508018712: // typeTList return this.typeTList; case 508942233: // typeUList return this.typeUList; case -1441181153: // typeTArray return this.typeTArray; case -1412552002: // typeUArray return this.typeUArray; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsComplexExtendsSuperTwoGenerics()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsComplexExtendsSuperTwoGenerics.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code normalType} property. * @return the meta-property, not null */ public final MetaProperty normalType() { return normalType; } /** * The meta-property for the {@code typeT} property. * @return the meta-property, not null */ public final MetaProperty typeT() { return typeT; } /** * The meta-property for the {@code typeU} property. * @return the meta-property, not null */ public final MetaProperty typeU() { return typeU; } /** * The meta-property for the {@code typeTList} property. * @return the meta-property, not null */ public final MetaProperty> typeTList() { return typeTList; } /** * The meta-property for the {@code typeUList} property. * @return the meta-property, not null */ public final MetaProperty> typeUList() { return typeUList; } /** * The meta-property for the {@code typeTArray} property. * @return the meta-property, not null */ public final MetaProperty typeTArray() { return typeTArray; } /** * The meta-property for the {@code typeUArray} property. * @return the meta-property, not null */ public final MetaProperty typeUArray() { return typeUArray; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getNormalType(); case 110843994: // typeT return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getTypeT(); case 110843995: // typeU return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getTypeU(); case 508018712: // typeTList return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getTypeTList(); case 508942233: // typeUList return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getTypeUList(); case -1441181153: // typeTArray return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getTypeTArray(); case -1412552002: // typeUArray return ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).getTypeUArray(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setNormalType((String) newValue); return; case 110843994: // typeT ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setTypeT((T) newValue); return; case 110843995: // typeU ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setTypeU((U) newValue); return; case 508018712: // typeTList ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setTypeTList((List) newValue); return; case 508942233: // typeUList ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setTypeUList((List) newValue); return; case -1441181153: // typeTArray ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setTypeTArray((T[]) newValue); return; case -1412552002: // typeUArray ((DoubleGenericsComplexExtendsSuperTwoGenerics) bean).setTypeUArray((U[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsNoExtendsNoSuper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsNoExtendsNoSuper implements Bean { /** The normal type. */ @PropertyDefinition private String normalType; /** The type T value. */ @PropertyDefinition private T typeT; /** The type U value. */ @PropertyDefinition private U typeU; /** The type T value. */ @PropertyDefinition private List typeTList; /** The type U value. */ @PropertyDefinition private List typeUList; /** The type T value. */ @PropertyDefinition private T[] typeTArray; /** The type U value. */ @PropertyDefinition private U[] typeUArray; /** * Creates an instance. */ public DoubleGenericsNoExtendsNoSuper() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsNoExtendsNoSuper}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsNoExtendsNoSuper.Meta meta() { return DoubleGenericsNoExtendsNoSuper.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsNoExtendsNoSuper}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static DoubleGenericsNoExtendsNoSuper.Meta metaDoubleGenericsNoExtendsNoSuper(Class cls1, Class cls2) { return DoubleGenericsNoExtendsNoSuper.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsNoExtendsNoSuper.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsNoExtendsNoSuper.Meta metaBean() { return DoubleGenericsNoExtendsNoSuper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getNormalType() { return normalType; } /** * Sets the normal type. * @param normalType the new value of the property */ public void setNormalType(String normalType) { this.normalType = normalType; } /** * Gets the the {@code normalType} property. * @return the property, not null */ public final Property normalType() { return metaBean().normalType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getTypeT() { return typeT; } /** * Sets the type T value. * @param typeT the new value of the property */ public void setTypeT(T typeT) { this.typeT = typeT; } /** * Gets the the {@code typeT} property. * @return the property, not null */ public final Property typeT() { return metaBean().typeT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getTypeU() { return typeU; } /** * Sets the type U value. * @param typeU the new value of the property */ public void setTypeU(U typeU) { this.typeU = typeU; } /** * Gets the the {@code typeU} property. * @return the property, not null */ public final Property typeU() { return metaBean().typeU().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public List getTypeTList() { return typeTList; } /** * Sets the type T value. * @param typeTList the new value of the property */ public void setTypeTList(List typeTList) { this.typeTList = typeTList; } /** * Gets the the {@code typeTList} property. * @return the property, not null */ public final Property> typeTList() { return metaBean().typeTList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public List getTypeUList() { return typeUList; } /** * Sets the type U value. * @param typeUList the new value of the property */ public void setTypeUList(List typeUList) { this.typeUList = typeUList; } /** * Gets the the {@code typeUList} property. * @return the property, not null */ public final Property> typeUList() { return metaBean().typeUList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T[] getTypeTArray() { return typeTArray; } /** * Sets the type T value. * @param typeTArray the new value of the property */ public void setTypeTArray(T[] typeTArray) { this.typeTArray = typeTArray; } /** * Gets the the {@code typeTArray} property. * @return the property, not null */ public final Property typeTArray() { return metaBean().typeTArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U[] getTypeUArray() { return typeUArray; } /** * Sets the type U value. * @param typeUArray the new value of the property */ public void setTypeUArray(U[] typeUArray) { this.typeUArray = typeUArray; } /** * Gets the the {@code typeUArray} property. * @return the property, not null */ public final Property typeUArray() { return metaBean().typeUArray().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsNoExtendsNoSuper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsNoExtendsNoSuper other = (DoubleGenericsNoExtendsNoSuper) obj; return JodaBeanUtils.equal(this.getNormalType(), other.getNormalType()) && JodaBeanUtils.equal(this.getTypeT(), other.getTypeT()) && JodaBeanUtils.equal(this.getTypeU(), other.getTypeU()) && JodaBeanUtils.equal(this.getTypeTList(), other.getTypeTList()) && JodaBeanUtils.equal(this.getTypeUList(), other.getTypeUList()) && JodaBeanUtils.equal(this.getTypeTArray(), other.getTypeTArray()) && JodaBeanUtils.equal(this.getTypeUArray(), other.getTypeUArray()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNormalType()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeT()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeU()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUArray()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("DoubleGenericsNoExtendsNoSuper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("normalType").append('=').append(JodaBeanUtils.toString(getNormalType())).append(',').append(' '); buf.append("typeT").append('=').append(JodaBeanUtils.toString(getTypeT())).append(',').append(' '); buf.append("typeU").append('=').append(JodaBeanUtils.toString(getTypeU())).append(',').append(' '); buf.append("typeTList").append('=').append(JodaBeanUtils.toString(getTypeTList())).append(',').append(' '); buf.append("typeUList").append('=').append(JodaBeanUtils.toString(getTypeUList())).append(',').append(' '); buf.append("typeTArray").append('=').append(JodaBeanUtils.toString(getTypeTArray())).append(',').append(' '); buf.append("typeUArray").append('=').append(JodaBeanUtils.toString(getTypeUArray())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsNoExtendsNoSuper}. * @param the type * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code normalType} property. */ private final MetaProperty normalType = DirectMetaProperty.ofReadWrite( this, "normalType", DoubleGenericsNoExtendsNoSuper.class, String.class); /** * The meta-property for the {@code typeT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeT", DoubleGenericsNoExtendsNoSuper.class, Object.class); /** * The meta-property for the {@code typeU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeU", DoubleGenericsNoExtendsNoSuper.class, Object.class); /** * The meta-property for the {@code typeTList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeTList = DirectMetaProperty.ofReadWrite( this, "typeTList", DoubleGenericsNoExtendsNoSuper.class, (Class) List.class); /** * The meta-property for the {@code typeUList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeUList = DirectMetaProperty.ofReadWrite( this, "typeUList", DoubleGenericsNoExtendsNoSuper.class, (Class) List.class); /** * The meta-property for the {@code typeTArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeTArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeTArray", DoubleGenericsNoExtendsNoSuper.class, Object[].class); /** * The meta-property for the {@code typeUArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeUArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeUArray", DoubleGenericsNoExtendsNoSuper.class, Object[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "normalType", "typeT", "typeU", "typeTList", "typeUList", "typeTArray", "typeUArray"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1255672639: // normalType return this.normalType; case 110843994: // typeT return this.typeT; case 110843995: // typeU return this.typeU; case 508018712: // typeTList return this.typeTList; case 508942233: // typeUList return this.typeUList; case -1441181153: // typeTArray return this.typeTArray; case -1412552002: // typeUArray return this.typeUArray; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsNoExtendsNoSuper()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsNoExtendsNoSuper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code normalType} property. * @return the meta-property, not null */ public final MetaProperty normalType() { return normalType; } /** * The meta-property for the {@code typeT} property. * @return the meta-property, not null */ public final MetaProperty typeT() { return typeT; } /** * The meta-property for the {@code typeU} property. * @return the meta-property, not null */ public final MetaProperty typeU() { return typeU; } /** * The meta-property for the {@code typeTList} property. * @return the meta-property, not null */ public final MetaProperty> typeTList() { return typeTList; } /** * The meta-property for the {@code typeUList} property. * @return the meta-property, not null */ public final MetaProperty> typeUList() { return typeUList; } /** * The meta-property for the {@code typeTArray} property. * @return the meta-property, not null */ public final MetaProperty typeTArray() { return typeTArray; } /** * The meta-property for the {@code typeUArray} property. * @return the meta-property, not null */ public final MetaProperty typeUArray() { return typeUArray; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType return ((DoubleGenericsNoExtendsNoSuper) bean).getNormalType(); case 110843994: // typeT return ((DoubleGenericsNoExtendsNoSuper) bean).getTypeT(); case 110843995: // typeU return ((DoubleGenericsNoExtendsNoSuper) bean).getTypeU(); case 508018712: // typeTList return ((DoubleGenericsNoExtendsNoSuper) bean).getTypeTList(); case 508942233: // typeUList return ((DoubleGenericsNoExtendsNoSuper) bean).getTypeUList(); case -1441181153: // typeTArray return ((DoubleGenericsNoExtendsNoSuper) bean).getTypeTArray(); case -1412552002: // typeUArray return ((DoubleGenericsNoExtendsNoSuper) bean).getTypeUArray(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType ((DoubleGenericsNoExtendsNoSuper) bean).setNormalType((String) newValue); return; case 110843994: // typeT ((DoubleGenericsNoExtendsNoSuper) bean).setTypeT((T) newValue); return; case 110843995: // typeU ((DoubleGenericsNoExtendsNoSuper) bean).setTypeU((U) newValue); return; case 508018712: // typeTList ((DoubleGenericsNoExtendsNoSuper) bean).setTypeTList((List) newValue); return; case 508942233: // typeUList ((DoubleGenericsNoExtendsNoSuper) bean).setTypeUList((List) newValue); return; case -1441181153: // typeTArray ((DoubleGenericsNoExtendsNoSuper) bean).setTypeTArray((T[]) newValue); return; case -1412552002: // typeUArray ((DoubleGenericsNoExtendsNoSuper) bean).setTypeUArray((U[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsSimpleSuper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsSimpleSuper implements Bean { /** The normal type. */ @PropertyDefinition private String baseType; /** The type T value. */ @PropertyDefinition private T baseT; /** The type U value. */ @PropertyDefinition private U baseU; /** * Creates an instance. */ public DoubleGenericsSimpleSuper() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsSimpleSuper}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsSimpleSuper.Meta meta() { return DoubleGenericsSimpleSuper.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsSimpleSuper}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static DoubleGenericsSimpleSuper.Meta metaDoubleGenericsSimpleSuper(Class cls1, Class cls2) { return DoubleGenericsSimpleSuper.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsSimpleSuper.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsSimpleSuper.Meta metaBean() { return DoubleGenericsSimpleSuper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getBaseType() { return baseType; } /** * Sets the normal type. * @param baseType the new value of the property */ public void setBaseType(String baseType) { this.baseType = baseType; } /** * Gets the the {@code baseType} property. * @return the property, not null */ public final Property baseType() { return metaBean().baseType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getBaseT() { return baseT; } /** * Sets the type T value. * @param baseT the new value of the property */ public void setBaseT(T baseT) { this.baseT = baseT; } /** * Gets the the {@code baseT} property. * @return the property, not null */ public final Property baseT() { return metaBean().baseT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getBaseU() { return baseU; } /** * Sets the type U value. * @param baseU the new value of the property */ public void setBaseU(U baseU) { this.baseU = baseU; } /** * Gets the the {@code baseU} property. * @return the property, not null */ public final Property baseU() { return metaBean().baseU().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsSimpleSuper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsSimpleSuper other = (DoubleGenericsSimpleSuper) obj; return JodaBeanUtils.equal(this.getBaseType(), other.getBaseType()) && JodaBeanUtils.equal(this.getBaseT(), other.getBaseT()) && JodaBeanUtils.equal(this.getBaseU(), other.getBaseU()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getBaseType()); hash = hash * 31 + JodaBeanUtils.hashCode(getBaseT()); hash = hash * 31 + JodaBeanUtils.hashCode(getBaseU()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("DoubleGenericsSimpleSuper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("baseType").append('=').append(JodaBeanUtils.toString(getBaseType())).append(',').append(' '); buf.append("baseT").append('=').append(JodaBeanUtils.toString(getBaseT())).append(',').append(' '); buf.append("baseU").append('=').append(JodaBeanUtils.toString(getBaseU())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsSimpleSuper}. * @param the type * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code baseType} property. */ private final MetaProperty baseType = DirectMetaProperty.ofReadWrite( this, "baseType", DoubleGenericsSimpleSuper.class, String.class); /** * The meta-property for the {@code baseT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty baseT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "baseT", DoubleGenericsSimpleSuper.class, Object.class); /** * The meta-property for the {@code baseU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty baseU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "baseU", DoubleGenericsSimpleSuper.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "baseType", "baseT", "baseU"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1721484885: // baseType return this.baseType; case 93508515: // baseT return this.baseT; case 93508516: // baseU return this.baseU; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsSimpleSuper()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsSimpleSuper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code baseType} property. * @return the meta-property, not null */ public final MetaProperty baseType() { return baseType; } /** * The meta-property for the {@code baseT} property. * @return the meta-property, not null */ public final MetaProperty baseT() { return baseT; } /** * The meta-property for the {@code baseU} property. * @return the meta-property, not null */ public final MetaProperty baseU() { return baseU; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1721484885: // baseType return ((DoubleGenericsSimpleSuper) bean).getBaseType(); case 93508515: // baseT return ((DoubleGenericsSimpleSuper) bean).getBaseT(); case 93508516: // baseU return ((DoubleGenericsSimpleSuper) bean).getBaseU(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1721484885: // baseType ((DoubleGenericsSimpleSuper) bean).setBaseType((String) newValue); return; case 93508515: // baseT ((DoubleGenericsSimpleSuper) bean).setBaseT((T) newValue); return; case 93508516: // baseU ((DoubleGenericsSimpleSuper) bean).setBaseU((U) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsWithExtendsNoSuper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsWithExtendsNoSuper implements Bean { /** The normal type. */ @PropertyDefinition private String normalType; /** The type T value. */ @PropertyDefinition private T typeT; /** The type U value. */ @PropertyDefinition private U typeU; /** The type T value. */ @PropertyDefinition private List typeTList; /** The type U value. */ @PropertyDefinition private List typeUList; /** The type T value. */ @PropertyDefinition private T[] typeTArray; /** The type U value. */ @PropertyDefinition private U[] typeUArray; /** The list of generic T as an array. */ @PropertyDefinition private List[] typeTArrayOfList; /** The list of generic T as an array. */ @PropertyDefinition private List[][] typeTArray2dOfList; /** * Creates an instance. */ public DoubleGenericsWithExtendsNoSuper() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsNoSuper}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsWithExtendsNoSuper.Meta meta() { return DoubleGenericsWithExtendsNoSuper.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsWithExtendsNoSuper}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static DoubleGenericsWithExtendsNoSuper.Meta metaDoubleGenericsWithExtendsNoSuper(Class cls1, Class cls2) { return DoubleGenericsWithExtendsNoSuper.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsWithExtendsNoSuper.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsWithExtendsNoSuper.Meta metaBean() { return DoubleGenericsWithExtendsNoSuper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getNormalType() { return normalType; } /** * Sets the normal type. * @param normalType the new value of the property */ public void setNormalType(String normalType) { this.normalType = normalType; } /** * Gets the the {@code normalType} property. * @return the property, not null */ public final Property normalType() { return metaBean().normalType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getTypeT() { return typeT; } /** * Sets the type T value. * @param typeT the new value of the property */ public void setTypeT(T typeT) { this.typeT = typeT; } /** * Gets the the {@code typeT} property. * @return the property, not null */ public final Property typeT() { return metaBean().typeT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getTypeU() { return typeU; } /** * Sets the type U value. * @param typeU the new value of the property */ public void setTypeU(U typeU) { this.typeU = typeU; } /** * Gets the the {@code typeU} property. * @return the property, not null */ public final Property typeU() { return metaBean().typeU().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public List getTypeTList() { return typeTList; } /** * Sets the type T value. * @param typeTList the new value of the property */ public void setTypeTList(List typeTList) { this.typeTList = typeTList; } /** * Gets the the {@code typeTList} property. * @return the property, not null */ public final Property> typeTList() { return metaBean().typeTList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public List getTypeUList() { return typeUList; } /** * Sets the type U value. * @param typeUList the new value of the property */ public void setTypeUList(List typeUList) { this.typeUList = typeUList; } /** * Gets the the {@code typeUList} property. * @return the property, not null */ public final Property> typeUList() { return metaBean().typeUList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T[] getTypeTArray() { return typeTArray; } /** * Sets the type T value. * @param typeTArray the new value of the property */ public void setTypeTArray(T[] typeTArray) { this.typeTArray = typeTArray; } /** * Gets the the {@code typeTArray} property. * @return the property, not null */ public final Property typeTArray() { return metaBean().typeTArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U[] getTypeUArray() { return typeUArray; } /** * Sets the type U value. * @param typeUArray the new value of the property */ public void setTypeUArray(U[] typeUArray) { this.typeUArray = typeUArray; } /** * Gets the the {@code typeUArray} property. * @return the property, not null */ public final Property typeUArray() { return metaBean().typeUArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the list of generic T as an array. * @return the value of the property */ public List[] getTypeTArrayOfList() { return typeTArrayOfList; } /** * Sets the list of generic T as an array. * @param typeTArrayOfList the new value of the property */ public void setTypeTArrayOfList(List[] typeTArrayOfList) { this.typeTArrayOfList = typeTArrayOfList; } /** * Gets the the {@code typeTArrayOfList} property. * @return the property, not null */ public final Property[]> typeTArrayOfList() { return metaBean().typeTArrayOfList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the list of generic T as an array. * @return the value of the property */ public List[][] getTypeTArray2dOfList() { return typeTArray2dOfList; } /** * Sets the list of generic T as an array. * @param typeTArray2dOfList the new value of the property */ public void setTypeTArray2dOfList(List[][] typeTArray2dOfList) { this.typeTArray2dOfList = typeTArray2dOfList; } /** * Gets the the {@code typeTArray2dOfList} property. * @return the property, not null */ public final Property[][]> typeTArray2dOfList() { return metaBean().typeTArray2dOfList().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsWithExtendsNoSuper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsWithExtendsNoSuper other = (DoubleGenericsWithExtendsNoSuper) obj; return JodaBeanUtils.equal(this.getNormalType(), other.getNormalType()) && JodaBeanUtils.equal(this.getTypeT(), other.getTypeT()) && JodaBeanUtils.equal(this.getTypeU(), other.getTypeU()) && JodaBeanUtils.equal(this.getTypeTList(), other.getTypeTList()) && JodaBeanUtils.equal(this.getTypeUList(), other.getTypeUList()) && JodaBeanUtils.equal(this.getTypeTArray(), other.getTypeTArray()) && JodaBeanUtils.equal(this.getTypeUArray(), other.getTypeUArray()) && JodaBeanUtils.equal(this.getTypeTArrayOfList(), other.getTypeTArrayOfList()) && JodaBeanUtils.equal(this.getTypeTArray2dOfList(), other.getTypeTArray2dOfList()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNormalType()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeT()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeU()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArrayOfList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray2dOfList()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("DoubleGenericsWithExtendsNoSuper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("normalType").append('=').append(JodaBeanUtils.toString(getNormalType())).append(',').append(' '); buf.append("typeT").append('=').append(JodaBeanUtils.toString(getTypeT())).append(',').append(' '); buf.append("typeU").append('=').append(JodaBeanUtils.toString(getTypeU())).append(',').append(' '); buf.append("typeTList").append('=').append(JodaBeanUtils.toString(getTypeTList())).append(',').append(' '); buf.append("typeUList").append('=').append(JodaBeanUtils.toString(getTypeUList())).append(',').append(' '); buf.append("typeTArray").append('=').append(JodaBeanUtils.toString(getTypeTArray())).append(',').append(' '); buf.append("typeUArray").append('=').append(JodaBeanUtils.toString(getTypeUArray())).append(',').append(' '); buf.append("typeTArrayOfList").append('=').append(JodaBeanUtils.toString(getTypeTArrayOfList())).append(',').append(' '); buf.append("typeTArray2dOfList").append('=').append(JodaBeanUtils.toString(getTypeTArray2dOfList())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsNoSuper}. * @param the type * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code normalType} property. */ private final MetaProperty normalType = DirectMetaProperty.ofReadWrite( this, "normalType", DoubleGenericsWithExtendsNoSuper.class, String.class); /** * The meta-property for the {@code typeT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeT", DoubleGenericsWithExtendsNoSuper.class, Object.class); /** * The meta-property for the {@code typeU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeU", DoubleGenericsWithExtendsNoSuper.class, Object.class); /** * The meta-property for the {@code typeTList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeTList = DirectMetaProperty.ofReadWrite( this, "typeTList", DoubleGenericsWithExtendsNoSuper.class, (Class) List.class); /** * The meta-property for the {@code typeUList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeUList = DirectMetaProperty.ofReadWrite( this, "typeUList", DoubleGenericsWithExtendsNoSuper.class, (Class) List.class); /** * The meta-property for the {@code typeTArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeTArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeTArray", DoubleGenericsWithExtendsNoSuper.class, Object[].class); /** * The meta-property for the {@code typeUArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeUArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeUArray", DoubleGenericsWithExtendsNoSuper.class, Object[].class); /** * The meta-property for the {@code typeTArrayOfList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty[]> typeTArrayOfList = DirectMetaProperty.ofReadWrite( this, "typeTArrayOfList", DoubleGenericsWithExtendsNoSuper.class, (Class) List.class); /** * The meta-property for the {@code typeTArray2dOfList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty[][]> typeTArray2dOfList = DirectMetaProperty.ofReadWrite( this, "typeTArray2dOfList", DoubleGenericsWithExtendsNoSuper.class, (Class) List.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "normalType", "typeT", "typeU", "typeTList", "typeUList", "typeTArray", "typeUArray", "typeTArrayOfList", "typeTArray2dOfList"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1255672639: // normalType return this.normalType; case 110843994: // typeT return this.typeT; case 110843995: // typeU return this.typeU; case 508018712: // typeTList return this.typeTList; case 508942233: // typeUList return this.typeUList; case -1441181153: // typeTArray return this.typeTArray; case -1412552002: // typeUArray return this.typeUArray; case -1497015788: // typeTArrayOfList return this.typeTArrayOfList; case -513079482: // typeTArray2dOfList return this.typeTArray2dOfList; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsWithExtendsNoSuper()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsWithExtendsNoSuper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code normalType} property. * @return the meta-property, not null */ public final MetaProperty normalType() { return normalType; } /** * The meta-property for the {@code typeT} property. * @return the meta-property, not null */ public final MetaProperty typeT() { return typeT; } /** * The meta-property for the {@code typeU} property. * @return the meta-property, not null */ public final MetaProperty typeU() { return typeU; } /** * The meta-property for the {@code typeTList} property. * @return the meta-property, not null */ public final MetaProperty> typeTList() { return typeTList; } /** * The meta-property for the {@code typeUList} property. * @return the meta-property, not null */ public final MetaProperty> typeUList() { return typeUList; } /** * The meta-property for the {@code typeTArray} property. * @return the meta-property, not null */ public final MetaProperty typeTArray() { return typeTArray; } /** * The meta-property for the {@code typeUArray} property. * @return the meta-property, not null */ public final MetaProperty typeUArray() { return typeUArray; } /** * The meta-property for the {@code typeTArrayOfList} property. * @return the meta-property, not null */ public final MetaProperty[]> typeTArrayOfList() { return typeTArrayOfList; } /** * The meta-property for the {@code typeTArray2dOfList} property. * @return the meta-property, not null */ public final MetaProperty[][]> typeTArray2dOfList() { return typeTArray2dOfList; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType return ((DoubleGenericsWithExtendsNoSuper) bean).getNormalType(); case 110843994: // typeT return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeT(); case 110843995: // typeU return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeU(); case 508018712: // typeTList return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeTList(); case 508942233: // typeUList return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeUList(); case -1441181153: // typeTArray return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeTArray(); case -1412552002: // typeUArray return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeUArray(); case -1497015788: // typeTArrayOfList return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeTArrayOfList(); case -513079482: // typeTArray2dOfList return ((DoubleGenericsWithExtendsNoSuper) bean).getTypeTArray2dOfList(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType ((DoubleGenericsWithExtendsNoSuper) bean).setNormalType((String) newValue); return; case 110843994: // typeT ((DoubleGenericsWithExtendsNoSuper) bean).setTypeT((T) newValue); return; case 110843995: // typeU ((DoubleGenericsWithExtendsNoSuper) bean).setTypeU((U) newValue); return; case 508018712: // typeTList ((DoubleGenericsWithExtendsNoSuper) bean).setTypeTList((List) newValue); return; case 508942233: // typeUList ((DoubleGenericsWithExtendsNoSuper) bean).setTypeUList((List) newValue); return; case -1441181153: // typeTArray ((DoubleGenericsWithExtendsNoSuper) bean).setTypeTArray((T[]) newValue); return; case -1412552002: // typeUArray ((DoubleGenericsWithExtendsNoSuper) bean).setTypeUArray((U[]) newValue); return; case -1497015788: // typeTArrayOfList ((DoubleGenericsWithExtendsNoSuper) bean).setTypeTArrayOfList((List[]) newValue); return; case -513079482: // typeTArray2dOfList ((DoubleGenericsWithExtendsNoSuper) bean).setTypeTArray2dOfList((List[][]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsWithExtendsSuperNoGenerics.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsWithExtendsSuperNoGenerics extends Company { /** The normal type. */ @PropertyDefinition private String normalType; /** The type T value. */ @PropertyDefinition private T typeT; /** The type U value. */ @PropertyDefinition private U typeU; /** The type T value. */ @PropertyDefinition private List typeTList; /** The type U value. */ @PropertyDefinition private List typeUList; /** The type T value. */ @PropertyDefinition private T[] typeTArray; /** The type U value. */ @PropertyDefinition private U[] typeUArray; /** * Creates an instance. */ public DoubleGenericsWithExtendsSuperNoGenerics() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperNoGenerics}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsWithExtendsSuperNoGenerics.Meta meta() { return DoubleGenericsWithExtendsSuperNoGenerics.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperNoGenerics}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static DoubleGenericsWithExtendsSuperNoGenerics.Meta metaDoubleGenericsWithExtendsSuperNoGenerics(Class cls1, Class cls2) { return DoubleGenericsWithExtendsSuperNoGenerics.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsWithExtendsSuperNoGenerics.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsWithExtendsSuperNoGenerics.Meta metaBean() { return DoubleGenericsWithExtendsSuperNoGenerics.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getNormalType() { return normalType; } /** * Sets the normal type. * @param normalType the new value of the property */ public void setNormalType(String normalType) { this.normalType = normalType; } /** * Gets the the {@code normalType} property. * @return the property, not null */ public final Property normalType() { return metaBean().normalType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getTypeT() { return typeT; } /** * Sets the type T value. * @param typeT the new value of the property */ public void setTypeT(T typeT) { this.typeT = typeT; } /** * Gets the the {@code typeT} property. * @return the property, not null */ public final Property typeT() { return metaBean().typeT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getTypeU() { return typeU; } /** * Sets the type U value. * @param typeU the new value of the property */ public void setTypeU(U typeU) { this.typeU = typeU; } /** * Gets the the {@code typeU} property. * @return the property, not null */ public final Property typeU() { return metaBean().typeU().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public List getTypeTList() { return typeTList; } /** * Sets the type T value. * @param typeTList the new value of the property */ public void setTypeTList(List typeTList) { this.typeTList = typeTList; } /** * Gets the the {@code typeTList} property. * @return the property, not null */ public final Property> typeTList() { return metaBean().typeTList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public List getTypeUList() { return typeUList; } /** * Sets the type U value. * @param typeUList the new value of the property */ public void setTypeUList(List typeUList) { this.typeUList = typeUList; } /** * Gets the the {@code typeUList} property. * @return the property, not null */ public final Property> typeUList() { return metaBean().typeUList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T[] getTypeTArray() { return typeTArray; } /** * Sets the type T value. * @param typeTArray the new value of the property */ public void setTypeTArray(T[] typeTArray) { this.typeTArray = typeTArray; } /** * Gets the the {@code typeTArray} property. * @return the property, not null */ public final Property typeTArray() { return metaBean().typeTArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U[] getTypeUArray() { return typeUArray; } /** * Sets the type U value. * @param typeUArray the new value of the property */ public void setTypeUArray(U[] typeUArray) { this.typeUArray = typeUArray; } /** * Gets the the {@code typeUArray} property. * @return the property, not null */ public final Property typeUArray() { return metaBean().typeUArray().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsWithExtendsSuperNoGenerics clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsWithExtendsSuperNoGenerics other = (DoubleGenericsWithExtendsSuperNoGenerics) obj; return JodaBeanUtils.equal(this.getNormalType(), other.getNormalType()) && JodaBeanUtils.equal(this.getTypeT(), other.getTypeT()) && JodaBeanUtils.equal(this.getTypeU(), other.getTypeU()) && JodaBeanUtils.equal(this.getTypeTList(), other.getTypeTList()) && JodaBeanUtils.equal(this.getTypeUList(), other.getTypeUList()) && JodaBeanUtils.equal(this.getTypeTArray(), other.getTypeTArray()) && JodaBeanUtils.equal(this.getTypeUArray(), other.getTypeUArray()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getNormalType()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeT()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeU()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUArray()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("DoubleGenericsWithExtendsSuperNoGenerics{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("normalType").append('=').append(JodaBeanUtils.toString(getNormalType())).append(',').append(' '); buf.append("typeT").append('=').append(JodaBeanUtils.toString(getTypeT())).append(',').append(' '); buf.append("typeU").append('=').append(JodaBeanUtils.toString(getTypeU())).append(',').append(' '); buf.append("typeTList").append('=').append(JodaBeanUtils.toString(getTypeTList())).append(',').append(' '); buf.append("typeUList").append('=').append(JodaBeanUtils.toString(getTypeUList())).append(',').append(' '); buf.append("typeTArray").append('=').append(JodaBeanUtils.toString(getTypeTArray())).append(',').append(' '); buf.append("typeUArray").append('=').append(JodaBeanUtils.toString(getTypeUArray())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperNoGenerics}. * @param the type * @param the type */ public static class Meta extends Company.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code normalType} property. */ private final MetaProperty normalType = DirectMetaProperty.ofReadWrite( this, "normalType", DoubleGenericsWithExtendsSuperNoGenerics.class, String.class); /** * The meta-property for the {@code typeT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeT", DoubleGenericsWithExtendsSuperNoGenerics.class, Object.class); /** * The meta-property for the {@code typeU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeU", DoubleGenericsWithExtendsSuperNoGenerics.class, Object.class); /** * The meta-property for the {@code typeTList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeTList = DirectMetaProperty.ofReadWrite( this, "typeTList", DoubleGenericsWithExtendsSuperNoGenerics.class, (Class) List.class); /** * The meta-property for the {@code typeUList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeUList = DirectMetaProperty.ofReadWrite( this, "typeUList", DoubleGenericsWithExtendsSuperNoGenerics.class, (Class) List.class); /** * The meta-property for the {@code typeTArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeTArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeTArray", DoubleGenericsWithExtendsSuperNoGenerics.class, Object[].class); /** * The meta-property for the {@code typeUArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeUArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeUArray", DoubleGenericsWithExtendsSuperNoGenerics.class, Object[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "normalType", "typeT", "typeU", "typeTList", "typeUList", "typeTArray", "typeUArray"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1255672639: // normalType return this.normalType; case 110843994: // typeT return this.typeT; case 110843995: // typeU return this.typeU; case 508018712: // typeTList return this.typeTList; case 508942233: // typeUList return this.typeUList; case -1441181153: // typeTArray return this.typeTArray; case -1412552002: // typeUArray return this.typeUArray; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsWithExtendsSuperNoGenerics()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsWithExtendsSuperNoGenerics.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code normalType} property. * @return the meta-property, not null */ public final MetaProperty normalType() { return normalType; } /** * The meta-property for the {@code typeT} property. * @return the meta-property, not null */ public final MetaProperty typeT() { return typeT; } /** * The meta-property for the {@code typeU} property. * @return the meta-property, not null */ public final MetaProperty typeU() { return typeU; } /** * The meta-property for the {@code typeTList} property. * @return the meta-property, not null */ public final MetaProperty> typeTList() { return typeTList; } /** * The meta-property for the {@code typeUList} property. * @return the meta-property, not null */ public final MetaProperty> typeUList() { return typeUList; } /** * The meta-property for the {@code typeTArray} property. * @return the meta-property, not null */ public final MetaProperty typeTArray() { return typeTArray; } /** * The meta-property for the {@code typeUArray} property. * @return the meta-property, not null */ public final MetaProperty typeUArray() { return typeUArray; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getNormalType(); case 110843994: // typeT return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getTypeT(); case 110843995: // typeU return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getTypeU(); case 508018712: // typeTList return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getTypeTList(); case 508942233: // typeUList return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getTypeUList(); case -1441181153: // typeTArray return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getTypeTArray(); case -1412552002: // typeUArray return ((DoubleGenericsWithExtendsSuperNoGenerics) bean).getTypeUArray(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setNormalType((String) newValue); return; case 110843994: // typeT ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setTypeT((T) newValue); return; case 110843995: // typeU ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setTypeU((U) newValue); return; case 508018712: // typeTList ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setTypeTList((List) newValue); return; case 508942233: // typeUList ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setTypeUList((List) newValue); return; case -1441181153: // typeTArray ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setTypeTArray((T[]) newValue); return; case -1412552002: // typeUArray ((DoubleGenericsWithExtendsSuperNoGenerics) bean).setTypeUArray((U[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsWithExtendsSuperOneGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsWithExtendsSuperOneGeneric extends Documentation { /** The normal type. */ @PropertyDefinition private String normalType; /** The type T value. */ @PropertyDefinition private T typeT; /** The type U value. */ @PropertyDefinition private U typeU; /** The type T value. */ @PropertyDefinition private List typeTList; /** The type U value. */ @PropertyDefinition private List typeUList; /** The type T value. */ @PropertyDefinition private T[] typeTArray; /** The type U value. */ @PropertyDefinition private U[] typeUArray; /** * Creates an instance. */ public DoubleGenericsWithExtendsSuperOneGeneric() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperOneGeneric}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsWithExtendsSuperOneGeneric.Meta meta() { return DoubleGenericsWithExtendsSuperOneGeneric.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperOneGeneric}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static DoubleGenericsWithExtendsSuperOneGeneric.Meta metaDoubleGenericsWithExtendsSuperOneGeneric(Class cls1, Class cls2) { return DoubleGenericsWithExtendsSuperOneGeneric.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsWithExtendsSuperOneGeneric.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsWithExtendsSuperOneGeneric.Meta metaBean() { return DoubleGenericsWithExtendsSuperOneGeneric.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getNormalType() { return normalType; } /** * Sets the normal type. * @param normalType the new value of the property */ public void setNormalType(String normalType) { this.normalType = normalType; } /** * Gets the the {@code normalType} property. * @return the property, not null */ public final Property normalType() { return metaBean().normalType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getTypeT() { return typeT; } /** * Sets the type T value. * @param typeT the new value of the property */ public void setTypeT(T typeT) { this.typeT = typeT; } /** * Gets the the {@code typeT} property. * @return the property, not null */ public final Property typeT() { return metaBean().typeT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getTypeU() { return typeU; } /** * Sets the type U value. * @param typeU the new value of the property */ public void setTypeU(U typeU) { this.typeU = typeU; } /** * Gets the the {@code typeU} property. * @return the property, not null */ public final Property typeU() { return metaBean().typeU().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public List getTypeTList() { return typeTList; } /** * Sets the type T value. * @param typeTList the new value of the property */ public void setTypeTList(List typeTList) { this.typeTList = typeTList; } /** * Gets the the {@code typeTList} property. * @return the property, not null */ public final Property> typeTList() { return metaBean().typeTList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public List getTypeUList() { return typeUList; } /** * Sets the type U value. * @param typeUList the new value of the property */ public void setTypeUList(List typeUList) { this.typeUList = typeUList; } /** * Gets the the {@code typeUList} property. * @return the property, not null */ public final Property> typeUList() { return metaBean().typeUList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T[] getTypeTArray() { return typeTArray; } /** * Sets the type T value. * @param typeTArray the new value of the property */ public void setTypeTArray(T[] typeTArray) { this.typeTArray = typeTArray; } /** * Gets the the {@code typeTArray} property. * @return the property, not null */ public final Property typeTArray() { return metaBean().typeTArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U[] getTypeUArray() { return typeUArray; } /** * Sets the type U value. * @param typeUArray the new value of the property */ public void setTypeUArray(U[] typeUArray) { this.typeUArray = typeUArray; } /** * Gets the the {@code typeUArray} property. * @return the property, not null */ public final Property typeUArray() { return metaBean().typeUArray().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsWithExtendsSuperOneGeneric clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsWithExtendsSuperOneGeneric other = (DoubleGenericsWithExtendsSuperOneGeneric) obj; return JodaBeanUtils.equal(this.getNormalType(), other.getNormalType()) && JodaBeanUtils.equal(this.getTypeT(), other.getTypeT()) && JodaBeanUtils.equal(this.getTypeU(), other.getTypeU()) && JodaBeanUtils.equal(this.getTypeTList(), other.getTypeTList()) && JodaBeanUtils.equal(this.getTypeUList(), other.getTypeUList()) && JodaBeanUtils.equal(this.getTypeTArray(), other.getTypeTArray()) && JodaBeanUtils.equal(this.getTypeUArray(), other.getTypeUArray()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getNormalType()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeT()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeU()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUArray()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("DoubleGenericsWithExtendsSuperOneGeneric{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("normalType").append('=').append(JodaBeanUtils.toString(getNormalType())).append(',').append(' '); buf.append("typeT").append('=').append(JodaBeanUtils.toString(getTypeT())).append(',').append(' '); buf.append("typeU").append('=').append(JodaBeanUtils.toString(getTypeU())).append(',').append(' '); buf.append("typeTList").append('=').append(JodaBeanUtils.toString(getTypeTList())).append(',').append(' '); buf.append("typeUList").append('=').append(JodaBeanUtils.toString(getTypeUList())).append(',').append(' '); buf.append("typeTArray").append('=').append(JodaBeanUtils.toString(getTypeTArray())).append(',').append(' '); buf.append("typeUArray").append('=').append(JodaBeanUtils.toString(getTypeUArray())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperOneGeneric}. * @param the type * @param the type */ public static class Meta extends Documentation.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code normalType} property. */ private final MetaProperty normalType = DirectMetaProperty.ofReadWrite( this, "normalType", DoubleGenericsWithExtendsSuperOneGeneric.class, String.class); /** * The meta-property for the {@code typeT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeT", DoubleGenericsWithExtendsSuperOneGeneric.class, Object.class); /** * The meta-property for the {@code typeU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeU", DoubleGenericsWithExtendsSuperOneGeneric.class, Object.class); /** * The meta-property for the {@code typeTList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeTList = DirectMetaProperty.ofReadWrite( this, "typeTList", DoubleGenericsWithExtendsSuperOneGeneric.class, (Class) List.class); /** * The meta-property for the {@code typeUList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeUList = DirectMetaProperty.ofReadWrite( this, "typeUList", DoubleGenericsWithExtendsSuperOneGeneric.class, (Class) List.class); /** * The meta-property for the {@code typeTArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeTArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeTArray", DoubleGenericsWithExtendsSuperOneGeneric.class, Object[].class); /** * The meta-property for the {@code typeUArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeUArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeUArray", DoubleGenericsWithExtendsSuperOneGeneric.class, Object[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "normalType", "typeT", "typeU", "typeTList", "typeUList", "typeTArray", "typeUArray"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1255672639: // normalType return this.normalType; case 110843994: // typeT return this.typeT; case 110843995: // typeU return this.typeU; case 508018712: // typeTList return this.typeTList; case 508942233: // typeUList return this.typeUList; case -1441181153: // typeTArray return this.typeTArray; case -1412552002: // typeUArray return this.typeUArray; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsWithExtendsSuperOneGeneric()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsWithExtendsSuperOneGeneric.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code normalType} property. * @return the meta-property, not null */ public final MetaProperty normalType() { return normalType; } /** * The meta-property for the {@code typeT} property. * @return the meta-property, not null */ public final MetaProperty typeT() { return typeT; } /** * The meta-property for the {@code typeU} property. * @return the meta-property, not null */ public final MetaProperty typeU() { return typeU; } /** * The meta-property for the {@code typeTList} property. * @return the meta-property, not null */ public final MetaProperty> typeTList() { return typeTList; } /** * The meta-property for the {@code typeUList} property. * @return the meta-property, not null */ public final MetaProperty> typeUList() { return typeUList; } /** * The meta-property for the {@code typeTArray} property. * @return the meta-property, not null */ public final MetaProperty typeTArray() { return typeTArray; } /** * The meta-property for the {@code typeUArray} property. * @return the meta-property, not null */ public final MetaProperty typeUArray() { return typeUArray; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getNormalType(); case 110843994: // typeT return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getTypeT(); case 110843995: // typeU return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getTypeU(); case 508018712: // typeTList return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getTypeTList(); case 508942233: // typeUList return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getTypeUList(); case -1441181153: // typeTArray return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getTypeTArray(); case -1412552002: // typeUArray return ((DoubleGenericsWithExtendsSuperOneGeneric) bean).getTypeUArray(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setNormalType((String) newValue); return; case 110843994: // typeT ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setTypeT((T) newValue); return; case 110843995: // typeU ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setTypeU((U) newValue); return; case 508018712: // typeTList ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setTypeTList((List) newValue); return; case 508942233: // typeUList ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setTypeUList((List) newValue); return; case -1441181153: // typeTArray ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setTypeTArray((T[]) newValue); return; case -1412552002: // typeUArray ((DoubleGenericsWithExtendsSuperOneGeneric) bean).setTypeUArray((U[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/DoubleGenericsWithExtendsSuperTwoGenerics.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class DoubleGenericsWithExtendsSuperTwoGenerics extends DoubleGenericsSimpleSuper { /** The normal type. */ @PropertyDefinition private String normalType; /** The type T value. */ @PropertyDefinition private T typeT; /** The type U value. */ @PropertyDefinition private U typeU; /** The type T value. */ @PropertyDefinition private List typeTList; /** The type U value. */ @PropertyDefinition private List typeUList; /** The type T value. */ @PropertyDefinition private T[] typeTArray; /** The type U value. */ @PropertyDefinition private U[] typeUArray; /** * Creates an instance. */ public DoubleGenericsWithExtendsSuperTwoGenerics() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperTwoGenerics}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static DoubleGenericsWithExtendsSuperTwoGenerics.Meta meta() { return DoubleGenericsWithExtendsSuperTwoGenerics.Meta.INSTANCE; } /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperTwoGenerics}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static DoubleGenericsWithExtendsSuperTwoGenerics.Meta metaDoubleGenericsWithExtendsSuperTwoGenerics(Class cls1, Class cls2) { return DoubleGenericsWithExtendsSuperTwoGenerics.Meta.INSTANCE; } static { MetaBean.register(DoubleGenericsWithExtendsSuperTwoGenerics.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public DoubleGenericsWithExtendsSuperTwoGenerics.Meta metaBean() { return DoubleGenericsWithExtendsSuperTwoGenerics.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the normal type. * @return the value of the property */ public String getNormalType() { return normalType; } /** * Sets the normal type. * @param normalType the new value of the property */ public void setNormalType(String normalType) { this.normalType = normalType; } /** * Gets the the {@code normalType} property. * @return the property, not null */ public final Property normalType() { return metaBean().normalType().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T getTypeT() { return typeT; } /** * Sets the type T value. * @param typeT the new value of the property */ public void setTypeT(T typeT) { this.typeT = typeT; } /** * Gets the the {@code typeT} property. * @return the property, not null */ public final Property typeT() { return metaBean().typeT().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U getTypeU() { return typeU; } /** * Sets the type U value. * @param typeU the new value of the property */ public void setTypeU(U typeU) { this.typeU = typeU; } /** * Gets the the {@code typeU} property. * @return the property, not null */ public final Property typeU() { return metaBean().typeU().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public List getTypeTList() { return typeTList; } /** * Sets the type T value. * @param typeTList the new value of the property */ public void setTypeTList(List typeTList) { this.typeTList = typeTList; } /** * Gets the the {@code typeTList} property. * @return the property, not null */ public final Property> typeTList() { return metaBean().typeTList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public List getTypeUList() { return typeUList; } /** * Sets the type U value. * @param typeUList the new value of the property */ public void setTypeUList(List typeUList) { this.typeUList = typeUList; } /** * Gets the the {@code typeUList} property. * @return the property, not null */ public final Property> typeUList() { return metaBean().typeUList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type T value. * @return the value of the property */ public T[] getTypeTArray() { return typeTArray; } /** * Sets the type T value. * @param typeTArray the new value of the property */ public void setTypeTArray(T[] typeTArray) { this.typeTArray = typeTArray; } /** * Gets the the {@code typeTArray} property. * @return the property, not null */ public final Property typeTArray() { return metaBean().typeTArray().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the type U value. * @return the value of the property */ public U[] getTypeUArray() { return typeUArray; } /** * Sets the type U value. * @param typeUArray the new value of the property */ public void setTypeUArray(U[] typeUArray) { this.typeUArray = typeUArray; } /** * Gets the the {@code typeUArray} property. * @return the property, not null */ public final Property typeUArray() { return metaBean().typeUArray().createProperty(this); } //----------------------------------------------------------------------- @Override public DoubleGenericsWithExtendsSuperTwoGenerics clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { DoubleGenericsWithExtendsSuperTwoGenerics other = (DoubleGenericsWithExtendsSuperTwoGenerics) obj; return JodaBeanUtils.equal(this.getNormalType(), other.getNormalType()) && JodaBeanUtils.equal(this.getTypeT(), other.getTypeT()) && JodaBeanUtils.equal(this.getTypeU(), other.getTypeU()) && JodaBeanUtils.equal(this.getTypeTList(), other.getTypeTList()) && JodaBeanUtils.equal(this.getTypeUList(), other.getTypeUList()) && JodaBeanUtils.equal(this.getTypeTArray(), other.getTypeTArray()) && JodaBeanUtils.equal(this.getTypeUArray(), other.getTypeUArray()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getNormalType()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeT()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeU()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUList()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeTArray()); hash = hash * 31 + JodaBeanUtils.hashCode(getTypeUArray()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("DoubleGenericsWithExtendsSuperTwoGenerics{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("normalType").append('=').append(JodaBeanUtils.toString(getNormalType())).append(',').append(' '); buf.append("typeT").append('=').append(JodaBeanUtils.toString(getTypeT())).append(',').append(' '); buf.append("typeU").append('=').append(JodaBeanUtils.toString(getTypeU())).append(',').append(' '); buf.append("typeTList").append('=').append(JodaBeanUtils.toString(getTypeTList())).append(',').append(' '); buf.append("typeUList").append('=').append(JodaBeanUtils.toString(getTypeUList())).append(',').append(' '); buf.append("typeTArray").append('=').append(JodaBeanUtils.toString(getTypeTArray())).append(',').append(' '); buf.append("typeUArray").append('=').append(JodaBeanUtils.toString(getTypeUArray())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code DoubleGenericsWithExtendsSuperTwoGenerics}. * @param the type * @param the type */ public static class Meta extends DoubleGenericsSimpleSuper.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code normalType} property. */ private final MetaProperty normalType = DirectMetaProperty.ofReadWrite( this, "normalType", DoubleGenericsWithExtendsSuperTwoGenerics.class, String.class); /** * The meta-property for the {@code typeT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeT = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeT", DoubleGenericsWithExtendsSuperTwoGenerics.class, Object.class); /** * The meta-property for the {@code typeU} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeU = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeU", DoubleGenericsWithExtendsSuperTwoGenerics.class, Object.class); /** * The meta-property for the {@code typeTList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeTList = DirectMetaProperty.ofReadWrite( this, "typeTList", DoubleGenericsWithExtendsSuperTwoGenerics.class, (Class) List.class); /** * The meta-property for the {@code typeUList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typeUList = DirectMetaProperty.ofReadWrite( this, "typeUList", DoubleGenericsWithExtendsSuperTwoGenerics.class, (Class) List.class); /** * The meta-property for the {@code typeTArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeTArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeTArray", DoubleGenericsWithExtendsSuperTwoGenerics.class, Object[].class); /** * The meta-property for the {@code typeUArray} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty typeUArray = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "typeUArray", DoubleGenericsWithExtendsSuperTwoGenerics.class, Object[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "normalType", "typeT", "typeU", "typeTList", "typeUList", "typeTArray", "typeUArray"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1255672639: // normalType return this.normalType; case 110843994: // typeT return this.typeT; case 110843995: // typeU return this.typeU; case 508018712: // typeTList return this.typeTList; case 508942233: // typeUList return this.typeUList; case -1441181153: // typeTArray return this.typeTArray; case -1412552002: // typeUArray return this.typeUArray; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new DoubleGenericsWithExtendsSuperTwoGenerics()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) DoubleGenericsWithExtendsSuperTwoGenerics.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code normalType} property. * @return the meta-property, not null */ public final MetaProperty normalType() { return normalType; } /** * The meta-property for the {@code typeT} property. * @return the meta-property, not null */ public final MetaProperty typeT() { return typeT; } /** * The meta-property for the {@code typeU} property. * @return the meta-property, not null */ public final MetaProperty typeU() { return typeU; } /** * The meta-property for the {@code typeTList} property. * @return the meta-property, not null */ public final MetaProperty> typeTList() { return typeTList; } /** * The meta-property for the {@code typeUList} property. * @return the meta-property, not null */ public final MetaProperty> typeUList() { return typeUList; } /** * The meta-property for the {@code typeTArray} property. * @return the meta-property, not null */ public final MetaProperty typeTArray() { return typeTArray; } /** * The meta-property for the {@code typeUArray} property. * @return the meta-property, not null */ public final MetaProperty typeUArray() { return typeUArray; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getNormalType(); case 110843994: // typeT return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getTypeT(); case 110843995: // typeU return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getTypeU(); case 508018712: // typeTList return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getTypeTList(); case 508942233: // typeUList return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getTypeUList(); case -1441181153: // typeTArray return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getTypeTArray(); case -1412552002: // typeUArray return ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).getTypeUArray(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1255672639: // normalType ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setNormalType((String) newValue); return; case 110843994: // typeT ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setTypeT((T) newValue); return; case 110843995: // typeU ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setTypeU((U) newValue); return; case 508018712: // typeTList ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setTypeTList((List) newValue); return; case 508942233: // typeUList ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setTypeUList((List) newValue); return; case -1441181153: // typeTArray ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setTypeTArray((T[]) newValue); return; case -1412552002: // typeUArray ((DoubleGenericsWithExtendsSuperTwoGenerics) bean).setTypeUArray((U[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/FieldNamesImmutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. */ @BeanDefinition(builderScope = "public", factoryName = "of") public final class FieldNamesImmutable implements ImmutableBean { /** Field named 'obj' to check for name clashes. */ @PropertyDefinition private final String obj; /** Field named 'other' to check for name clashes. */ @PropertyDefinition private final String other; /** Field named 'propertyName' to check for name clashes. */ @PropertyDefinition private final String propertyName; /** Field named 'newValue' to check for name clashes. */ @PropertyDefinition private final String newValue; /** Field named 'bean' to check for name clashes. */ @PropertyDefinition private final String bean; /** Field named 'beanToCopy' to check for name clashes. */ @PropertyDefinition private final String beanToCopy; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code FieldNamesImmutable}. * @return the meta-bean, not null */ public static FieldNamesImmutable.Meta meta() { return FieldNamesImmutable.Meta.INSTANCE; } static { MetaBean.register(FieldNamesImmutable.Meta.INSTANCE); } /** * Obtains an instance. * @param obj the value of the property * @param other the value of the property * @param propertyName the value of the property * @param newValue the value of the property * @param bean the value of the property * @param beanToCopy the value of the property * @return the instance */ public static FieldNamesImmutable of( String obj, String other, String propertyName, String newValue, String bean, String beanToCopy) { return new FieldNamesImmutable( obj, other, propertyName, newValue, bean, beanToCopy); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static FieldNamesImmutable.Builder builder() { return new FieldNamesImmutable.Builder(); } private FieldNamesImmutable( String obj, String other, String propertyName, String newValue, String bean, String beanToCopy) { this.obj = obj; this.other = other; this.propertyName = propertyName; this.newValue = newValue; this.bean = bean; this.beanToCopy = beanToCopy; } @Override public FieldNamesImmutable.Meta metaBean() { return FieldNamesImmutable.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets field named 'obj' to check for name clashes. * @return the value of the property */ public String getObj() { return obj; } //----------------------------------------------------------------------- /** * Gets field named 'other' to check for name clashes. * @return the value of the property */ public String getOther() { return other; } //----------------------------------------------------------------------- /** * Gets field named 'propertyName' to check for name clashes. * @return the value of the property */ public String getPropertyName() { return propertyName; } //----------------------------------------------------------------------- /** * Gets field named 'newValue' to check for name clashes. * @return the value of the property */ public String getNewValue() { return newValue; } //----------------------------------------------------------------------- /** * Gets field named 'bean' to check for name clashes. * @return the value of the property */ public String getBean() { return bean; } //----------------------------------------------------------------------- /** * Gets field named 'beanToCopy' to check for name clashes. * @return the value of the property */ public String getBeanToCopy() { return beanToCopy; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { FieldNamesImmutable other = (FieldNamesImmutable) obj; return JodaBeanUtils.equal(this.obj, other.obj) && JodaBeanUtils.equal(this.other, other.other) && JodaBeanUtils.equal(this.propertyName, other.propertyName) && JodaBeanUtils.equal(this.newValue, other.newValue) && JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.beanToCopy, other.beanToCopy); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(obj); hash = hash * 31 + JodaBeanUtils.hashCode(other); hash = hash * 31 + JodaBeanUtils.hashCode(propertyName); hash = hash * 31 + JodaBeanUtils.hashCode(newValue); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(beanToCopy); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesImmutable{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code FieldNamesImmutable}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code obj} property. */ private final MetaProperty obj = DirectMetaProperty.ofImmutable( this, "obj", FieldNamesImmutable.class, String.class); /** * The meta-property for the {@code other} property. */ private final MetaProperty other = DirectMetaProperty.ofImmutable( this, "other", FieldNamesImmutable.class, String.class); /** * The meta-property for the {@code propertyName} property. */ private final MetaProperty propertyName = DirectMetaProperty.ofImmutable( this, "propertyName", FieldNamesImmutable.class, String.class); /** * The meta-property for the {@code newValue} property. */ private final MetaProperty newValue = DirectMetaProperty.ofImmutable( this, "newValue", FieldNamesImmutable.class, String.class); /** * The meta-property for the {@code bean} property. */ private final MetaProperty bean = DirectMetaProperty.ofImmutable( this, "bean", FieldNamesImmutable.class, String.class); /** * The meta-property for the {@code beanToCopy} property. */ private final MetaProperty beanToCopy = DirectMetaProperty.ofImmutable( this, "beanToCopy", FieldNamesImmutable.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "obj", "other", "propertyName", "newValue", "bean", "beanToCopy"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 109815: // obj return this.obj; case 106069776: // other return this.other; case -864691712: // propertyName return this.propertyName; case 1368456113: // newValue return this.newValue; case 3019696: // bean return this.bean; case -1343227808: // beanToCopy return this.beanToCopy; } return super.metaPropertyGet(propertyName); } @Override public FieldNamesImmutable.Builder builder() { return new FieldNamesImmutable.Builder(); } @Override public Class beanType() { return FieldNamesImmutable.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code obj} property. * @return the meta-property, not null */ public MetaProperty obj() { return obj; } /** * The meta-property for the {@code other} property. * @return the meta-property, not null */ public MetaProperty other() { return other; } /** * The meta-property for the {@code propertyName} property. * @return the meta-property, not null */ public MetaProperty propertyName() { return propertyName; } /** * The meta-property for the {@code newValue} property. * @return the meta-property, not null */ public MetaProperty newValue() { return newValue; } /** * The meta-property for the {@code bean} property. * @return the meta-property, not null */ public MetaProperty bean() { return bean; } /** * The meta-property for the {@code beanToCopy} property. * @return the meta-property, not null */ public MetaProperty beanToCopy() { return beanToCopy; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 109815: // obj return ((FieldNamesImmutable) bean).getObj(); case 106069776: // other return ((FieldNamesImmutable) bean).getOther(); case -864691712: // propertyName return ((FieldNamesImmutable) bean).getPropertyName(); case 1368456113: // newValue return ((FieldNamesImmutable) bean).getNewValue(); case 3019696: // bean return ((FieldNamesImmutable) bean).getBean(); case -1343227808: // beanToCopy return ((FieldNamesImmutable) bean).getBeanToCopy(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code FieldNamesImmutable}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String obj; private String other; private String propertyName; private String newValue; private String bean; private String beanToCopy; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(FieldNamesImmutable beanToCopy) { this.obj = beanToCopy.getObj(); this.other = beanToCopy.getOther(); this.propertyName = beanToCopy.getPropertyName(); this.newValue = beanToCopy.getNewValue(); this.bean = beanToCopy.getBean(); this.beanToCopy = beanToCopy.getBeanToCopy(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 109815: // obj return this.obj; case 106069776: // other return this.other; case -864691712: // propertyName return this.propertyName; case 1368456113: // newValue return this.newValue; case 3019696: // bean return this.bean; case -1343227808: // beanToCopy return this.beanToCopy; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 109815: // obj this.obj = (String) newValue; break; case 106069776: // other this.other = (String) newValue; break; case -864691712: // propertyName this.propertyName = (String) newValue; break; case 1368456113: // newValue this.newValue = (String) newValue; break; case 3019696: // bean this.bean = (String) newValue; break; case -1343227808: // beanToCopy this.beanToCopy = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public FieldNamesImmutable build() { return new FieldNamesImmutable( obj, other, propertyName, newValue, bean, beanToCopy); } //----------------------------------------------------------------------- /** * Sets field named 'obj' to check for name clashes. * @param obj the new value * @return this, for chaining, not null */ public Builder obj(String obj) { this.obj = obj; return this; } /** * Sets field named 'other' to check for name clashes. * @param other the new value * @return this, for chaining, not null */ public Builder other(String other) { this.other = other; return this; } /** * Sets field named 'propertyName' to check for name clashes. * @param propertyName the new value * @return this, for chaining, not null */ public Builder propertyName(String propertyName) { this.propertyName = propertyName; return this; } /** * Sets field named 'newValue' to check for name clashes. * @param newValue the new value * @return this, for chaining, not null */ public Builder newValue(String newValue) { this.newValue = newValue; return this; } /** * Sets field named 'bean' to check for name clashes. * @param bean the new value * @return this, for chaining, not null */ public Builder bean(String bean) { this.bean = bean; return this; } /** * Sets field named 'beanToCopy' to check for name clashes. * @param beanToCopy the new value * @return this, for chaining, not null */ public Builder beanToCopy(String beanToCopy) { this.beanToCopy = beanToCopy; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesImmutable.Builder{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/FieldNamesImmutableMinimal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock JavaBean, used for testing. */ @BeanDefinition(style = "minimal") public final class FieldNamesImmutableMinimal implements ImmutableBean { /** Field named 'obj' to check for name clashes. */ @PropertyDefinition(get = "field") private final String obj; /** Field named 'other' to check for name clashes. */ @PropertyDefinition(get = "field") private final String other; /** Field named 'propertyName' to check for name clashes. */ @PropertyDefinition(get = "field") private final String propertyName; /** Field named 'newValue' to check for name clashes. */ @PropertyDefinition(get = "field") private final String newValue; /** Field named 'bean' to check for name clashes. */ @PropertyDefinition(get = "field") private final String bean; /** Field named 'beanToCopy' to check for name clashes. */ @PropertyDefinition(get = "field") private final String beanToCopy; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code FieldNamesImmutableMinimal}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( FieldNamesImmutableMinimal.class, new String[] { "obj", "other", "propertyName", "newValue", "bean", "beanToCopy"}, () -> new FieldNamesImmutableMinimal.Builder(), b -> b.obj, b -> b.other, b -> b.propertyName, b -> b.newValue, b -> b.bean, b -> b.beanToCopy); /** * The meta-bean for {@code FieldNamesImmutableMinimal}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static FieldNamesImmutableMinimal.Builder builder() { return new FieldNamesImmutableMinimal.Builder(); } private FieldNamesImmutableMinimal( String obj, String other, String propertyName, String newValue, String bean, String beanToCopy) { this.obj = obj; this.other = other; this.propertyName = propertyName; this.newValue = newValue; this.bean = bean; this.beanToCopy = beanToCopy; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { FieldNamesImmutableMinimal other = (FieldNamesImmutableMinimal) obj; return JodaBeanUtils.equal(this.obj, other.obj) && JodaBeanUtils.equal(this.other, other.other) && JodaBeanUtils.equal(this.propertyName, other.propertyName) && JodaBeanUtils.equal(this.newValue, other.newValue) && JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.beanToCopy, other.beanToCopy); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(obj); hash = hash * 31 + JodaBeanUtils.hashCode(other); hash = hash * 31 + JodaBeanUtils.hashCode(propertyName); hash = hash * 31 + JodaBeanUtils.hashCode(newValue); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(beanToCopy); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesImmutableMinimal{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code FieldNamesImmutableMinimal}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String obj; private String other; private String propertyName; private String newValue; private String bean; private String beanToCopy; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(FieldNamesImmutableMinimal beanToCopy) { this.obj = beanToCopy.obj; this.other = beanToCopy.other; this.propertyName = beanToCopy.propertyName; this.newValue = beanToCopy.newValue; this.bean = beanToCopy.bean; this.beanToCopy = beanToCopy.beanToCopy; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 109815: // obj return this.obj; case 106069776: // other return this.other; case -864691712: // propertyName return this.propertyName; case 1368456113: // newValue return this.newValue; case 3019696: // bean return this.bean; case -1343227808: // beanToCopy return this.beanToCopy; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 109815: // obj this.obj = (String) newValue; break; case 106069776: // other this.other = (String) newValue; break; case -864691712: // propertyName this.propertyName = (String) newValue; break; case 1368456113: // newValue this.newValue = (String) newValue; break; case 3019696: // bean this.bean = (String) newValue; break; case -1343227808: // beanToCopy this.beanToCopy = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public FieldNamesImmutableMinimal build() { return new FieldNamesImmutableMinimal( obj, other, propertyName, newValue, bean, beanToCopy); } //----------------------------------------------------------------------- /** * Sets field named 'obj' to check for name clashes. * @param obj the new value * @return this, for chaining, not null */ public Builder obj(String obj) { this.obj = obj; return this; } /** * Sets field named 'other' to check for name clashes. * @param other the new value * @return this, for chaining, not null */ public Builder other(String other) { this.other = other; return this; } /** * Sets field named 'propertyName' to check for name clashes. * @param propertyName the new value * @return this, for chaining, not null */ public Builder propertyName(String propertyName) { this.propertyName = propertyName; return this; } /** * Sets field named 'newValue' to check for name clashes. * @param newValue the new value * @return this, for chaining, not null */ public Builder newValue(String newValue) { this.newValue = newValue; return this; } /** * Sets field named 'bean' to check for name clashes. * @param bean the new value * @return this, for chaining, not null */ public Builder bean(String bean) { this.bean = bean; return this; } /** * Sets field named 'beanToCopy' to check for name clashes. * @param beanToCopy the new value * @return this, for chaining, not null */ public Builder beanToCopy(String beanToCopy) { this.beanToCopy = beanToCopy; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesImmutableMinimal.Builder{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/FieldNamesLight.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.invoke.MethodHandles; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; /** * Mock JavaBean, used for testing. */ @BeanDefinition(style = "light", builderScope = "public") public final class FieldNamesLight implements ImmutableBean { /** Field named 'obj' to check for name clashes. */ @PropertyDefinition(get = "field") private final String obj; /** Field named 'other' to check for name clashes. */ @PropertyDefinition(get = "field") private final String other; /** Field named 'propertyName' to check for name clashes. */ @PropertyDefinition(get = "field") private final String propertyName; /** Field named 'newValue' to check for name clashes. */ @PropertyDefinition(get = "field") private final String newValue; /** Field named 'bean' to check for name clashes. */ @PropertyDefinition(get = "field") private final String bean; /** Field named 'beanToCopy' to check for name clashes. */ @PropertyDefinition(get = "field") private final String beanToCopy; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code FieldNamesLight}. */ private static final TypedMetaBean META_BEAN = LightMetaBean.of( FieldNamesLight.class, MethodHandles.lookup(), new String[] { "obj", "other", "propertyName", "newValue", "bean", "beanToCopy"}, new Object[0]); /** * The meta-bean for {@code FieldNamesLight}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } private FieldNamesLight( String obj, String other, String propertyName, String newValue, String bean, String beanToCopy) { this.obj = obj; this.other = other; this.propertyName = propertyName; this.newValue = newValue; this.bean = bean; this.beanToCopy = beanToCopy; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { FieldNamesLight other = (FieldNamesLight) obj; return JodaBeanUtils.equal(this.obj, other.obj) && JodaBeanUtils.equal(this.other, other.other) && JodaBeanUtils.equal(this.propertyName, other.propertyName) && JodaBeanUtils.equal(this.newValue, other.newValue) && JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.beanToCopy, other.beanToCopy); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(obj); hash = hash * 31 + JodaBeanUtils.hashCode(other); hash = hash * 31 + JodaBeanUtils.hashCode(propertyName); hash = hash * 31 + JodaBeanUtils.hashCode(newValue); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(beanToCopy); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesLight{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/FieldNamesMutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. */ @BeanDefinition(builderScope = "public") public final class FieldNamesMutable implements Bean { /** Field named 'obj' to check for name clashes. */ @PropertyDefinition(get = "field") private String obj; /** Field named 'other' to check for name clashes. */ @PropertyDefinition(get = "field") private String other; /** Field named 'propertyName' to check for name clashes. */ @PropertyDefinition(get = "field") private String propertyName; /** Field named 'newValue' to check for name clashes. */ @PropertyDefinition(get = "field") private String newValue; /** Field named 'bean' to check for name clashes. */ @PropertyDefinition(get = "field") private String bean; /** Field named 'beanToCopy' to check for name clashes. */ @PropertyDefinition(get = "field") private String beanToCopy; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code FieldNamesMutable}. * @return the meta-bean, not null */ public static FieldNamesMutable.Meta meta() { return FieldNamesMutable.Meta.INSTANCE; } static { MetaBean.register(FieldNamesMutable.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static FieldNamesMutable.Builder builder() { return new FieldNamesMutable.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ private FieldNamesMutable(FieldNamesMutable.Builder builder) { this.obj = builder.obj; this.other = builder.other; this.propertyName = builder.propertyName; this.newValue = builder.newValue; this.bean = builder.bean; this.beanToCopy = builder.beanToCopy; } @Override public FieldNamesMutable.Meta metaBean() { return FieldNamesMutable.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Sets field named 'obj' to check for name clashes. * @param obj the new value of the property */ public void setObj(String obj) { this.obj = obj; } /** * Gets the the {@code obj} property. * @return the property, not null */ public Property obj() { return metaBean().obj().createProperty(this); } //----------------------------------------------------------------------- /** * Sets field named 'other' to check for name clashes. * @param other the new value of the property */ public void setOther(String other) { this.other = other; } /** * Gets the the {@code other} property. * @return the property, not null */ public Property other() { return metaBean().other().createProperty(this); } //----------------------------------------------------------------------- /** * Sets field named 'propertyName' to check for name clashes. * @param propertyName the new value of the property */ public void setPropertyName(String propertyName) { this.propertyName = propertyName; } /** * Gets the the {@code propertyName} property. * @return the property, not null */ public Property propertyName() { return metaBean().propertyName().createProperty(this); } //----------------------------------------------------------------------- /** * Sets field named 'newValue' to check for name clashes. * @param newValue the new value of the property */ public void setNewValue(String newValue) { this.newValue = newValue; } /** * Gets the the {@code newValue} property. * @return the property, not null */ public Property newValue() { return metaBean().newValue().createProperty(this); } //----------------------------------------------------------------------- /** * Sets field named 'bean' to check for name clashes. * @param bean the new value of the property */ public void setBean(String bean) { this.bean = bean; } /** * Gets the the {@code bean} property. * @return the property, not null */ public Property bean() { return metaBean().bean().createProperty(this); } //----------------------------------------------------------------------- /** * Sets field named 'beanToCopy' to check for name clashes. * @param beanToCopy the new value of the property */ public void setBeanToCopy(String beanToCopy) { this.beanToCopy = beanToCopy; } /** * Gets the the {@code beanToCopy} property. * @return the property, not null */ public Property beanToCopy() { return metaBean().beanToCopy().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public FieldNamesMutable clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { FieldNamesMutable other = (FieldNamesMutable) obj; return JodaBeanUtils.equal(this.obj, other.obj) && JodaBeanUtils.equal(this.other, other.other) && JodaBeanUtils.equal(this.propertyName, other.propertyName) && JodaBeanUtils.equal(this.newValue, other.newValue) && JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.beanToCopy, other.beanToCopy); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(obj); hash = hash * 31 + JodaBeanUtils.hashCode(other); hash = hash * 31 + JodaBeanUtils.hashCode(propertyName); hash = hash * 31 + JodaBeanUtils.hashCode(newValue); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(beanToCopy); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesMutable{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code FieldNamesMutable}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code obj} property. */ private final MetaProperty obj = DirectMetaProperty.ofReadWrite( this, "obj", FieldNamesMutable.class, String.class); /** * The meta-property for the {@code other} property. */ private final MetaProperty other = DirectMetaProperty.ofReadWrite( this, "other", FieldNamesMutable.class, String.class); /** * The meta-property for the {@code propertyName} property. */ private final MetaProperty propertyName = DirectMetaProperty.ofReadWrite( this, "propertyName", FieldNamesMutable.class, String.class); /** * The meta-property for the {@code newValue} property. */ private final MetaProperty newValue = DirectMetaProperty.ofReadWrite( this, "newValue", FieldNamesMutable.class, String.class); /** * The meta-property for the {@code bean} property. */ private final MetaProperty bean = DirectMetaProperty.ofReadWrite( this, "bean", FieldNamesMutable.class, String.class); /** * The meta-property for the {@code beanToCopy} property. */ private final MetaProperty beanToCopy = DirectMetaProperty.ofReadWrite( this, "beanToCopy", FieldNamesMutable.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "obj", "other", "propertyName", "newValue", "bean", "beanToCopy"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 109815: // obj return this.obj; case 106069776: // other return this.other; case -864691712: // propertyName return this.propertyName; case 1368456113: // newValue return this.newValue; case 3019696: // bean return this.bean; case -1343227808: // beanToCopy return this.beanToCopy; } return super.metaPropertyGet(propertyName); } @Override public FieldNamesMutable.Builder builder() { return new FieldNamesMutable.Builder(); } @Override public Class beanType() { return FieldNamesMutable.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code obj} property. * @return the meta-property, not null */ public MetaProperty obj() { return obj; } /** * The meta-property for the {@code other} property. * @return the meta-property, not null */ public MetaProperty other() { return other; } /** * The meta-property for the {@code propertyName} property. * @return the meta-property, not null */ public MetaProperty propertyName() { return propertyName; } /** * The meta-property for the {@code newValue} property. * @return the meta-property, not null */ public MetaProperty newValue() { return newValue; } /** * The meta-property for the {@code bean} property. * @return the meta-property, not null */ public MetaProperty bean() { return bean; } /** * The meta-property for the {@code beanToCopy} property. * @return the meta-property, not null */ public MetaProperty beanToCopy() { return beanToCopy; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 109815: // obj return ((FieldNamesMutable) bean).obj; case 106069776: // other return ((FieldNamesMutable) bean).other; case -864691712: // propertyName return ((FieldNamesMutable) bean).propertyName; case 1368456113: // newValue return ((FieldNamesMutable) bean).newValue; case 3019696: // bean return ((FieldNamesMutable) bean).bean; case -1343227808: // beanToCopy return ((FieldNamesMutable) bean).beanToCopy; } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 109815: // obj ((FieldNamesMutable) bean).setObj((String) newValue); return; case 106069776: // other ((FieldNamesMutable) bean).setOther((String) newValue); return; case -864691712: // propertyName ((FieldNamesMutable) bean).setPropertyName((String) newValue); return; case 1368456113: // newValue ((FieldNamesMutable) bean).setNewValue((String) newValue); return; case 3019696: // bean ((FieldNamesMutable) bean).setBean((String) newValue); return; case -1343227808: // beanToCopy ((FieldNamesMutable) bean).setBeanToCopy((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code FieldNamesMutable}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String obj; private String other; private String propertyName; private String newValue; private String bean; private String beanToCopy; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(FieldNamesMutable beanToCopy) { this.obj = beanToCopy.obj; this.other = beanToCopy.other; this.propertyName = beanToCopy.propertyName; this.newValue = beanToCopy.newValue; this.bean = beanToCopy.bean; this.beanToCopy = beanToCopy.beanToCopy; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 109815: // obj return this.obj; case 106069776: // other return this.other; case -864691712: // propertyName return this.propertyName; case 1368456113: // newValue return this.newValue; case 3019696: // bean return this.bean; case -1343227808: // beanToCopy return this.beanToCopy; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 109815: // obj this.obj = (String) newValue; break; case 106069776: // other this.other = (String) newValue; break; case -864691712: // propertyName this.propertyName = (String) newValue; break; case 1368456113: // newValue this.newValue = (String) newValue; break; case 3019696: // bean this.bean = (String) newValue; break; case -1343227808: // beanToCopy this.beanToCopy = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public FieldNamesMutable build() { return new FieldNamesMutable(this); } //----------------------------------------------------------------------- /** * Sets field named 'obj' to check for name clashes. * @param obj the new value * @return this, for chaining, not null */ public Builder obj(String obj) { this.obj = obj; return this; } /** * Sets field named 'other' to check for name clashes. * @param other the new value * @return this, for chaining, not null */ public Builder other(String other) { this.other = other; return this; } /** * Sets field named 'propertyName' to check for name clashes. * @param propertyName the new value * @return this, for chaining, not null */ public Builder propertyName(String propertyName) { this.propertyName = propertyName; return this; } /** * Sets field named 'newValue' to check for name clashes. * @param newValue the new value * @return this, for chaining, not null */ public Builder newValue(String newValue) { this.newValue = newValue; return this; } /** * Sets field named 'bean' to check for name clashes. * @param bean the new value * @return this, for chaining, not null */ public Builder bean(String bean) { this.bean = bean; return this; } /** * Sets field named 'beanToCopy' to check for name clashes. * @param beanToCopy the new value * @return this, for chaining, not null */ public Builder beanToCopy(String beanToCopy) { this.beanToCopy = beanToCopy; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesMutable.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/FieldNamesMutableMinimal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Arrays; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.BasicBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock JavaBean, used for testing. */ @BeanDefinition(style = "minimal") public final class FieldNamesMutableMinimal implements Bean { /** Field named 'obj' to check for name clashes. */ @PropertyDefinition(get = "field") private String obj; /** Field named 'other' to check for name clashes. */ @PropertyDefinition(get = "field") private String other; /** Field named 'propertyName' to check for name clashes. */ @PropertyDefinition(get = "field") private String propertyName; /** Field named 'newValue' to check for name clashes. */ @PropertyDefinition(get = "field") private String newValue; /** Field named 'bean' to check for name clashes. */ @PropertyDefinition(get = "field") private String bean; /** Field named 'beanToCopy' to check for name clashes. */ @PropertyDefinition(get = "field") private String beanToCopy; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code FieldNamesMutableMinimal}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( FieldNamesMutableMinimal.class, new String[] { "obj", "other", "propertyName", "newValue", "bean", "beanToCopy"}, () -> new BasicBeanBuilder<>(new FieldNamesMutableMinimal()), Arrays.>asList( b -> b.obj, b -> b.other, b -> b.propertyName, b -> b.newValue, b -> b.bean, b -> b.beanToCopy), Arrays.>asList( (b, v) -> b.setObj((String) v), (b, v) -> b.setOther((String) v), (b, v) -> b.setPropertyName((String) v), (b, v) -> b.setNewValue((String) v), (b, v) -> b.setBean((String) v), (b, v) -> b.setBeanToCopy((String) v))); /** * The meta-bean for {@code FieldNamesMutableMinimal}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Sets field named 'obj' to check for name clashes. * @param obj the new value of the property */ public void setObj(String obj) { this.obj = obj; } //----------------------------------------------------------------------- /** * Sets field named 'other' to check for name clashes. * @param other the new value of the property */ public void setOther(String other) { this.other = other; } //----------------------------------------------------------------------- /** * Sets field named 'propertyName' to check for name clashes. * @param propertyName the new value of the property */ public void setPropertyName(String propertyName) { this.propertyName = propertyName; } //----------------------------------------------------------------------- /** * Sets field named 'newValue' to check for name clashes. * @param newValue the new value of the property */ public void setNewValue(String newValue) { this.newValue = newValue; } //----------------------------------------------------------------------- /** * Sets field named 'bean' to check for name clashes. * @param bean the new value of the property */ public void setBean(String bean) { this.bean = bean; } //----------------------------------------------------------------------- /** * Sets field named 'beanToCopy' to check for name clashes. * @param beanToCopy the new value of the property */ public void setBeanToCopy(String beanToCopy) { this.beanToCopy = beanToCopy; } //----------------------------------------------------------------------- @Override public FieldNamesMutableMinimal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { FieldNamesMutableMinimal other = (FieldNamesMutableMinimal) obj; return JodaBeanUtils.equal(this.obj, other.obj) && JodaBeanUtils.equal(this.other, other.other) && JodaBeanUtils.equal(this.propertyName, other.propertyName) && JodaBeanUtils.equal(this.newValue, other.newValue) && JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.beanToCopy, other.beanToCopy); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(obj); hash = hash * 31 + JodaBeanUtils.hashCode(other); hash = hash * 31 + JodaBeanUtils.hashCode(propertyName); hash = hash * 31 + JodaBeanUtils.hashCode(newValue); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(beanToCopy); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("FieldNamesMutableMinimal{"); buf.append("obj").append('=').append(JodaBeanUtils.toString(obj)).append(',').append(' '); buf.append("other").append('=').append(JodaBeanUtils.toString(other)).append(',').append(' '); buf.append("propertyName").append('=').append(JodaBeanUtils.toString(propertyName)).append(',').append(' '); buf.append("newValue").append('=').append(JodaBeanUtils.toString(newValue)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("beanToCopy").append('=').append(JodaBeanUtils.toString(beanToCopy)); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/FinalFieldBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.impl.flexi.FlexiBean; /** * Mock used for test equals. * * @author Stephen Colebourne */ @BeanDefinition public class FinalFieldBean extends DirectBean { /** * The field that is final. */ @PropertyDefinition private final String fieldFinal; /** * The field that is not final. */ @PropertyDefinition private String fieldNonFinal; /** * The list that is final. */ @PropertyDefinition private final List listFinal = new ArrayList<>(); /** * The flexi that is final. */ @PropertyDefinition private final FlexiBean flexiFinal = new FlexiBean(); /** * The person that is final. */ @PropertyDefinition private final Person personFinal = new Person(); /** * Creates an instance. */ public FinalFieldBean() { this.fieldFinal = null; } /** * Creates an instance. * * @param fieldFinal the final field */ public FinalFieldBean(String fieldFinal) { this.fieldFinal = fieldFinal; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code FinalFieldBean}. * @return the meta-bean, not null */ public static FinalFieldBean.Meta meta() { return FinalFieldBean.Meta.INSTANCE; } static { MetaBean.register(FinalFieldBean.Meta.INSTANCE); } @Override public FinalFieldBean.Meta metaBean() { return FinalFieldBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the field that is final. * @return the value of the property */ public String getFieldFinal() { return fieldFinal; } /** * Gets the the {@code fieldFinal} property. * @return the property, not null */ public final Property fieldFinal() { return metaBean().fieldFinal().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the field that is not final. * @return the value of the property */ public String getFieldNonFinal() { return fieldNonFinal; } /** * Sets the field that is not final. * @param fieldNonFinal the new value of the property */ public void setFieldNonFinal(String fieldNonFinal) { this.fieldNonFinal = fieldNonFinal; } /** * Gets the the {@code fieldNonFinal} property. * @return the property, not null */ public final Property fieldNonFinal() { return metaBean().fieldNonFinal().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the list that is final. * @return the value of the property, not null */ public List getListFinal() { return listFinal; } /** * Sets the list that is final. * @param listFinal the new value of the property, not null */ public void setListFinal(List listFinal) { JodaBeanUtils.notNull(listFinal, "listFinal"); this.listFinal.clear(); this.listFinal.addAll(listFinal); } /** * Gets the the {@code listFinal} property. * @return the property, not null */ public final Property> listFinal() { return metaBean().listFinal().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the flexi that is final. * @return the value of the property, not null */ public FlexiBean getFlexiFinal() { return flexiFinal; } /** * Sets the flexi that is final. * @param flexiFinal the new value of the property, not null */ public void setFlexiFinal(FlexiBean flexiFinal) { JodaBeanUtils.notNull(flexiFinal, "flexiFinal"); this.flexiFinal.clear(); this.flexiFinal.putAll(flexiFinal); } /** * Gets the the {@code flexiFinal} property. * @return the property, not null */ public final Property flexiFinal() { return metaBean().flexiFinal().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the person that is final. * @return the value of the property, not null */ public Person getPersonFinal() { return personFinal; } /** * Gets the the {@code personFinal} property. * @return the property, not null */ public final Property personFinal() { return metaBean().personFinal().createProperty(this); } //----------------------------------------------------------------------- @Override public FinalFieldBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { FinalFieldBean other = (FinalFieldBean) obj; return JodaBeanUtils.equal(this.getFieldFinal(), other.getFieldFinal()) && JodaBeanUtils.equal(this.getFieldNonFinal(), other.getFieldNonFinal()) && JodaBeanUtils.equal(this.getListFinal(), other.getListFinal()) && JodaBeanUtils.equal(this.getFlexiFinal(), other.getFlexiFinal()) && JodaBeanUtils.equal(this.getPersonFinal(), other.getPersonFinal()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getFieldFinal()); hash = hash * 31 + JodaBeanUtils.hashCode(getFieldNonFinal()); hash = hash * 31 + JodaBeanUtils.hashCode(getListFinal()); hash = hash * 31 + JodaBeanUtils.hashCode(getFlexiFinal()); hash = hash * 31 + JodaBeanUtils.hashCode(getPersonFinal()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(192); buf.append("FinalFieldBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("fieldFinal").append('=').append(JodaBeanUtils.toString(getFieldFinal())).append(',').append(' '); buf.append("fieldNonFinal").append('=').append(JodaBeanUtils.toString(getFieldNonFinal())).append(',').append(' '); buf.append("listFinal").append('=').append(JodaBeanUtils.toString(getListFinal())).append(',').append(' '); buf.append("flexiFinal").append('=').append(JodaBeanUtils.toString(getFlexiFinal())).append(',').append(' '); buf.append("personFinal").append('=').append(JodaBeanUtils.toString(getPersonFinal())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code FinalFieldBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code fieldFinal} property. */ private final MetaProperty fieldFinal = DirectMetaProperty.ofReadOnly( this, "fieldFinal", FinalFieldBean.class, String.class); /** * The meta-property for the {@code fieldNonFinal} property. */ private final MetaProperty fieldNonFinal = DirectMetaProperty.ofReadWrite( this, "fieldNonFinal", FinalFieldBean.class, String.class); /** * The meta-property for the {@code listFinal} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listFinal = DirectMetaProperty.ofReadWrite( this, "listFinal", FinalFieldBean.class, (Class) List.class); /** * The meta-property for the {@code flexiFinal} property. */ private final MetaProperty flexiFinal = DirectMetaProperty.ofReadWrite( this, "flexiFinal", FinalFieldBean.class, FlexiBean.class); /** * The meta-property for the {@code personFinal} property. */ private final MetaProperty personFinal = DirectMetaProperty.ofReadOnly( this, "personFinal", FinalFieldBean.class, Person.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "fieldFinal", "fieldNonFinal", "listFinal", "flexiFinal", "personFinal"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 553434268: // fieldFinal return this.fieldFinal; case 1043548611: // fieldNonFinal return this.fieldNonFinal; case -1247489160: // listFinal return this.listFinal; case 1629293510: // flexiFinal return this.flexiFinal; case -448986335: // personFinal return this.personFinal; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new FinalFieldBean()); } @Override public Class beanType() { return FinalFieldBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code fieldFinal} property. * @return the meta-property, not null */ public final MetaProperty fieldFinal() { return fieldFinal; } /** * The meta-property for the {@code fieldNonFinal} property. * @return the meta-property, not null */ public final MetaProperty fieldNonFinal() { return fieldNonFinal; } /** * The meta-property for the {@code listFinal} property. * @return the meta-property, not null */ public final MetaProperty> listFinal() { return listFinal; } /** * The meta-property for the {@code flexiFinal} property. * @return the meta-property, not null */ public final MetaProperty flexiFinal() { return flexiFinal; } /** * The meta-property for the {@code personFinal} property. * @return the meta-property, not null */ public final MetaProperty personFinal() { return personFinal; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 553434268: // fieldFinal return ((FinalFieldBean) bean).getFieldFinal(); case 1043548611: // fieldNonFinal return ((FinalFieldBean) bean).getFieldNonFinal(); case -1247489160: // listFinal return ((FinalFieldBean) bean).getListFinal(); case 1629293510: // flexiFinal return ((FinalFieldBean) bean).getFlexiFinal(); case -448986335: // personFinal return ((FinalFieldBean) bean).getPersonFinal(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 553434268: // fieldFinal if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: fieldFinal"); case 1043548611: // fieldNonFinal ((FinalFieldBean) bean).setFieldNonFinal((String) newValue); return; case -1247489160: // listFinal ((FinalFieldBean) bean).setListFinal((List) newValue); return; case 1629293510: // flexiFinal ((FinalFieldBean) bean).setFlexiFinal((FlexiBean) newValue); return; case -448986335: // personFinal if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: personFinal"); } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((FinalFieldBean) bean).listFinal, "listFinal"); JodaBeanUtils.notNull(((FinalFieldBean) bean).flexiFinal, "flexiFinal"); JodaBeanUtils.notNull(((FinalFieldBean) bean).personFinal, "personFinal"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericAllFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class GenericAllFinal implements Bean { /** The name. */ @PropertyDefinition(validate = "notNull") private final String name; /** The value. */ @PropertyDefinition(validate = "notNull") private final T value; public GenericAllFinal() { name = "foo"; value = null; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code GenericAllFinal}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static GenericAllFinal.Meta meta() { return GenericAllFinal.Meta.INSTANCE; } /** * The meta-bean for {@code GenericAllFinal}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static GenericAllFinal.Meta metaGenericAllFinal(Class cls) { return GenericAllFinal.Meta.INSTANCE; } static { MetaBean.register(GenericAllFinal.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public GenericAllFinal.Meta metaBean() { return GenericAllFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public String getName() { return name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property, not null */ public T getValue() { return value; } /** * Gets the the {@code value} property. * @return the property, not null */ public final Property value() { return metaBean().value().createProperty(this); } //----------------------------------------------------------------------- @Override public GenericAllFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { GenericAllFinal other = (GenericAllFinal) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && JodaBeanUtils.equal(this.getValue(), other.getValue()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getName()); hash = hash * 31 + JodaBeanUtils.hashCode(getValue()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("GenericAllFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); buf.append("value").append('=').append(JodaBeanUtils.toString(getValue())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code GenericAllFinal}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadOnly( this, "name", GenericAllFinal.class, String.class); /** * The meta-property for the {@code value} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty value = (DirectMetaProperty) DirectMetaProperty.ofReadOnly( this, "value", GenericAllFinal.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name", "value"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new GenericAllFinal()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) GenericAllFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public final MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((GenericAllFinal) bean).getName(); case 111972721: // value return ((GenericAllFinal) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: name"); case 111972721: // value if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: value"); } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((GenericAllFinal) bean).name, "name"); JodaBeanUtils.notNull(((GenericAllFinal) bean).value, "value"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericArray.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class GenericArray implements Bean { /** The name. */ @PropertyDefinition(validate = "notNull") private T[] values; @PropertyDefinition(get = "cloneArray", set = "cloneArray") private int[][] intArray2d; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code GenericArray}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static GenericArray.Meta meta() { return GenericArray.Meta.INSTANCE; } /** * The meta-bean for {@code GenericArray}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static GenericArray.Meta metaGenericArray(Class cls) { return GenericArray.Meta.INSTANCE; } static { MetaBean.register(GenericArray.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public GenericArray.Meta metaBean() { return GenericArray.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public T[] getValues() { return values; } /** * Sets the name. * @param values the new value of the property, not null */ public void setValues(T[] values) { JodaBeanUtils.notNull(values, "values"); this.values = values; } /** * Gets the the {@code values} property. * @return the property, not null */ public final Property values() { return metaBean().values().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the intArray2d. * @return the value of the property */ public int[][] getIntArray2d() { return (int[][]) JodaBeanUtils.cloneArray(intArray2d); } /** * Sets the intArray2d. * @param intArray2d the new value of the property */ public void setIntArray2d(int[][] intArray2d) { this.intArray2d = (int[][]) JodaBeanUtils.cloneArray(intArray2d); } /** * Gets the the {@code intArray2d} property. * @return the property, not null */ public final Property intArray2d() { return metaBean().intArray2d().createProperty(this); } //----------------------------------------------------------------------- @Override public GenericArray clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { GenericArray other = (GenericArray) obj; return JodaBeanUtils.equal(this.getValues(), other.getValues()) && JodaBeanUtils.equal(this.getIntArray2d(), other.getIntArray2d()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getValues()); hash = hash * 31 + JodaBeanUtils.hashCode(getIntArray2d()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("GenericArray{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("values").append('=').append(JodaBeanUtils.toString(getValues())).append(',').append(' '); buf.append("intArray2d").append('=').append(JodaBeanUtils.toString(getIntArray2d())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code GenericArray}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code values} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty values = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "values", GenericArray.class, Object[].class); /** * The meta-property for the {@code intArray2d} property. */ private final MetaProperty intArray2d = DirectMetaProperty.ofReadWrite( this, "intArray2d", GenericArray.class, int[][].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "values", "intArray2d"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -823812830: // values return this.values; case 822168476: // intArray2d return this.intArray2d; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new GenericArray()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) GenericArray.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code values} property. * @return the meta-property, not null */ public final MetaProperty values() { return values; } /** * The meta-property for the {@code intArray2d} property. * @return the meta-property, not null */ public final MetaProperty intArray2d() { return intArray2d; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -823812830: // values return ((GenericArray) bean).getValues(); case 822168476: // intArray2d return ((GenericArray) bean).getIntArray2d(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -823812830: // values ((GenericArray) bean).setValues((T[]) newValue); return; case 822168476: // intArray2d ((GenericArray) bean).setIntArray2d((int[][]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((GenericArray) bean).values, "values"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericInterfaceBase.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; /** * Mock, used for testing. * @param the type */ public interface GenericInterfaceBase { public abstract List getBase1(); } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericInterfaceChild.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; /** * Mock, used for testing. * @param the type */ public interface GenericInterfaceChild extends GenericInterfaceBase { @Override public abstract List getBase1(); } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericInterfaceImpl.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; /** * Mock, used for testing. */ public abstract class GenericInterfaceImpl extends GenericInterfaceMid { } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericInterfaceMid.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.math.BigDecimal; /** * Mock, used for testing. * * @param the type */ public abstract class GenericInterfaceMid implements GenericInterfaceChild { } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericSubWrapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class GenericSubWrapper extends Wrapper { /** The name. */ @PropertyDefinition(validate = "notNull") private String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code GenericSubWrapper}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static GenericSubWrapper.Meta meta() { return GenericSubWrapper.Meta.INSTANCE; } /** * The meta-bean for {@code GenericSubWrapper}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static GenericSubWrapper.Meta metaGenericSubWrapper(Class cls) { return GenericSubWrapper.Meta.INSTANCE; } static { MetaBean.register(GenericSubWrapper.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public GenericSubWrapper.Meta metaBean() { return GenericSubWrapper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property, not null */ public void setName(String name) { JodaBeanUtils.notNull(name, "name"); this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- @Override public GenericSubWrapper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { GenericSubWrapper other = (GenericSubWrapper) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("GenericSubWrapper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code GenericSubWrapper}. * @param the type */ public static class Meta extends Wrapper.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", GenericSubWrapper.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "name"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new GenericSubWrapper()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) GenericSubWrapper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((GenericSubWrapper) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((GenericSubWrapper) bean).setName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((GenericSubWrapper) bean).name, "name"); super.validate(bean); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericUnionType.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class GenericUnionType implements Bean { /** The name. */ @PropertyDefinition(validate = "notNull") private String name; /** The value. */ @PropertyDefinition(validate = "notNull") private T value; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code GenericUnionType}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static GenericUnionType.Meta meta() { return GenericUnionType.Meta.INSTANCE; } /** * The meta-bean for {@code GenericUnionType}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static GenericUnionType.Meta metaGenericUnionType(Class cls) { return GenericUnionType.Meta.INSTANCE; } static { MetaBean.register(GenericUnionType.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public GenericUnionType.Meta metaBean() { return GenericUnionType.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property, not null */ public void setName(String name) { JodaBeanUtils.notNull(name, "name"); this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property, not null */ public T getValue() { return value; } /** * Sets the value. * @param value the new value of the property, not null */ public void setValue(T value) { JodaBeanUtils.notNull(value, "value"); this.value = value; } /** * Gets the the {@code value} property. * @return the property, not null */ public final Property value() { return metaBean().value().createProperty(this); } //----------------------------------------------------------------------- @Override public GenericUnionType clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { GenericUnionType other = (GenericUnionType) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && JodaBeanUtils.equal(this.getValue(), other.getValue()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getName()); hash = hash * 31 + JodaBeanUtils.hashCode(getValue()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("GenericUnionType{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); buf.append("value").append('=').append(JodaBeanUtils.toString(getValue())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code GenericUnionType}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", GenericUnionType.class, String.class); /** * The meta-property for the {@code value} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty value = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "value", GenericUnionType.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name", "value"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new GenericUnionType()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) GenericUnionType.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public final MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((GenericUnionType) bean).getName(); case 111972721: // value return ((GenericUnionType) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((GenericUnionType) bean).setName((String) newValue); return; case 111972721: // value ((GenericUnionType) bean).setValue((T) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((GenericUnionType) bean).name, "name"); JodaBeanUtils.notNull(((GenericUnionType) bean).value, "value"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/GenericWrapperDocumentation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class GenericWrapperDocumentation extends Documentation> { /** The name. */ @PropertyDefinition private String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code GenericWrapperDocumentation}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static GenericWrapperDocumentation.Meta meta() { return GenericWrapperDocumentation.Meta.INSTANCE; } /** * The meta-bean for {@code GenericWrapperDocumentation}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static GenericWrapperDocumentation.Meta metaGenericWrapperDocumentation(Class cls) { return GenericWrapperDocumentation.Meta.INSTANCE; } static { MetaBean.register(GenericWrapperDocumentation.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public GenericWrapperDocumentation.Meta metaBean() { return GenericWrapperDocumentation.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property */ public void setName(String name) { this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- @Override public GenericWrapperDocumentation clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { GenericWrapperDocumentation other = (GenericWrapperDocumentation) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("GenericWrapperDocumentation{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code GenericWrapperDocumentation}. * @param the type */ public static class Meta extends Documentation.Meta> { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", GenericWrapperDocumentation.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "name"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new GenericWrapperDocumentation()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) GenericWrapperDocumentation.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((GenericWrapperDocumentation) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((GenericWrapperDocumentation) bean).setName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/IKey.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; /** * Mock key interface, used for testing. */ public interface IKey { /** * Gets the name of the key. * * @return the name */ String getName(); } ================================================ FILE: src/test/java/org/joda/beans/sample/INamedKey.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.convert.FromString; import org.joda.convert.ToString; /** * Mock key Joda-Convert extending an interface, used for testing. */ public interface INamedKey extends IKey { @FromString public static INamedKey of(String uniqueName) { return ImmNamedKey.of(uniqueName); } /** * Gets the name. * The name is unique in conjunction with the type. * @return the value of the property, not empty */ @Override @ToString public abstract String getName(); } ================================================ FILE: src/test/java/org/joda/beans/sample/IPerson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; /** * Mock person interface, used for testing. */ public interface IPerson { /** * Gets the forename. * @return the value of the property */ String getForename(); /** * Gets the surname. * @return the value of the property */ String getSurname(); /** * Sets the surname. * @param surname the new value of the property */ void setSurname(String surname); } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmAddress.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Arrays; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.collect.grid.Grid; import org.joda.collect.grid.ImmutableGrid; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Table; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "private") public final class ImmAddress implements ImmutableBean, Serializable { /** * The number. * This will be the flat, house number or house name. */ @PropertyDefinition private final int number; /** * The street. */ @PropertyDefinition(validate = "notNull") private final String street; /** * The city. */ @PropertyDefinition(validate = "notNull") private final String city; /** * The abstract number. */ @PropertyDefinition private final Number abstractNumber; /** * The extra data. */ @PropertyDefinition private final byte[] data; /** * The 2D array. */ @PropertyDefinition private final String[][] array2d; /** * The owner. */ @PropertyDefinition(validate = "notNull") private final ImmPerson owner; /** * The object field. */ @PropertyDefinition private final Object object1; /** * The object field. */ @PropertyDefinition private final Object object2; /** * The risk field. */ @PropertyDefinition private final Risk risk; /** * The risk level field, testing an {@code Enum}. */ @PropertyDefinition private final RiskLevel riskLevel; /** * The risk levels field, testing {@code EnumSet}. */ @PropertyDefinition private final EnumSet riskLevels; /** * The serializable field. */ @PropertyDefinition private final Serializable serializable; /** * The object in map field. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap objectInMap; /** * The list in map field. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap> listInMap; /** * The list in map field. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap> listNumericInMap; /** * The list in list in map field. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap>> listInListInMap; /** * The object list in list in map field. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap>> objectListInListInMap; /** * The map in map field. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap> mapInMap; /** * The simple table. */ @PropertyDefinition private final ImmutableTable simpleTable; /** * The compound table. */ @PropertyDefinition private final ImmutableTable compoundTable; /** * The grid. */ @PropertyDefinition private final ImmutableGrid sparseGrid; /** * The grid. */ @PropertyDefinition @SimpleAnnotation(first = "a", second = "b", third = "c") private final ImmutableGrid denseGrid; /** * The bean key and bean value field. */ @PropertyDefinition(validate = "notNull") // comment is ignored private final ImmutableMap beanBeanMap; /** * The array. */ @PropertyDefinition private final double[] doubleVector; /** * The matrix. */ @PropertyDefinition private final double[][] matrix; // blank line above is ignored //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmAddress}. * @return the meta-bean, not null */ public static ImmAddress.Meta meta() { return ImmAddress.Meta.INSTANCE; } static { MetaBean.register(ImmAddress.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmAddress.Builder builder() { return new ImmAddress.Builder(); } private ImmAddress( int number, String street, String city, Number abstractNumber, byte[] data, String[][] array2d, ImmPerson owner, Object object1, Object object2, Risk risk, RiskLevel riskLevel, Set riskLevels, Serializable serializable, Map objectInMap, Map> listInMap, Map> listNumericInMap, Map>> listInListInMap, Map>> objectListInListInMap, Map> mapInMap, Table simpleTable, Table compoundTable, Grid sparseGrid, Grid denseGrid, Map beanBeanMap, double[] doubleVector, double[][] matrix) { JodaBeanUtils.notNull(street, "street"); JodaBeanUtils.notNull(city, "city"); JodaBeanUtils.notNull(owner, "owner"); JodaBeanUtils.notNull(objectInMap, "objectInMap"); JodaBeanUtils.notNull(listInMap, "listInMap"); JodaBeanUtils.notNull(listNumericInMap, "listNumericInMap"); JodaBeanUtils.notNull(listInListInMap, "listInListInMap"); JodaBeanUtils.notNull(objectListInListInMap, "objectListInListInMap"); JodaBeanUtils.notNull(mapInMap, "mapInMap"); JodaBeanUtils.notNull(beanBeanMap, "beanBeanMap"); this.number = number; this.street = street; this.city = city; this.abstractNumber = abstractNumber; this.data = (data != null ? data.clone() : null); this.array2d = (String[][]) JodaBeanUtils.cloneArray(array2d); this.owner = owner; this.object1 = object1; this.object2 = object2; this.risk = risk; this.riskLevel = riskLevel; this.riskLevels = (riskLevels != null ? EnumSet.copyOf(riskLevels) : null); this.serializable = serializable; this.objectInMap = ImmutableMap.copyOf(objectInMap); this.listInMap = ImmutableMap.copyOf(listInMap); this.listNumericInMap = ImmutableMap.copyOf(listNumericInMap); this.listInListInMap = ImmutableMap.copyOf(listInListInMap); this.objectListInListInMap = ImmutableMap.copyOf(objectListInListInMap); this.mapInMap = ImmutableMap.copyOf(mapInMap); this.simpleTable = (simpleTable != null ? ImmutableTable.copyOf(simpleTable) : null); this.compoundTable = (compoundTable != null ? ImmutableTable.copyOf(compoundTable) : null); this.sparseGrid = (sparseGrid != null ? ImmutableGrid.copyOf(sparseGrid) : null); this.denseGrid = (denseGrid != null ? ImmutableGrid.copyOf(denseGrid) : null); this.beanBeanMap = ImmutableMap.copyOf(beanBeanMap); this.doubleVector = (doubleVector != null ? doubleVector.clone() : null); this.matrix = (double[][]) JodaBeanUtils.cloneArray(matrix); } @Override public ImmAddress.Meta metaBean() { return ImmAddress.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the number. * This will be the flat, house number or house name. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the street. * @return the value of the property, not null */ public String getStreet() { return street; } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } //----------------------------------------------------------------------- /** * Gets the abstract number. * @return the value of the property */ public Number getAbstractNumber() { return abstractNumber; } //----------------------------------------------------------------------- /** * Gets the extra data. * @return the value of the property */ public byte[] getData() { return (data != null ? data.clone() : null); } //----------------------------------------------------------------------- /** * Gets the 2D array. * @return the value of the property */ public String[][] getArray2d() { return (String[][]) JodaBeanUtils.cloneArray(array2d); } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property, not null */ public ImmPerson getOwner() { return owner; } //----------------------------------------------------------------------- /** * Gets the object field. * @return the value of the property */ public Object getObject1() { return object1; } //----------------------------------------------------------------------- /** * Gets the object field. * @return the value of the property */ public Object getObject2() { return object2; } //----------------------------------------------------------------------- /** * Gets the risk field. * @return the value of the property */ public Risk getRisk() { return risk; } //----------------------------------------------------------------------- /** * Gets the risk level field, testing an {@code Enum}. * @return the value of the property */ public RiskLevel getRiskLevel() { return riskLevel; } //----------------------------------------------------------------------- /** * Gets the risk levels field, testing {@code EnumSet}. * @return the value of the property */ public EnumSet getRiskLevels() { return riskLevels; } //----------------------------------------------------------------------- /** * Gets the serializable field. * @return the value of the property */ public Serializable getSerializable() { return serializable; } //----------------------------------------------------------------------- /** * Gets the object in map field. * @return the value of the property, not null */ public ImmutableMap getObjectInMap() { return objectInMap; } //----------------------------------------------------------------------- /** * Gets the list in map field. * @return the value of the property, not null */ public ImmutableMap> getListInMap() { return listInMap; } //----------------------------------------------------------------------- /** * Gets the list in map field. * @return the value of the property, not null */ public ImmutableMap> getListNumericInMap() { return listNumericInMap; } //----------------------------------------------------------------------- /** * Gets the list in list in map field. * @return the value of the property, not null */ public ImmutableMap>> getListInListInMap() { return listInListInMap; } //----------------------------------------------------------------------- /** * Gets the object list in list in map field. * @return the value of the property, not null */ public ImmutableMap>> getObjectListInListInMap() { return objectListInListInMap; } //----------------------------------------------------------------------- /** * Gets the map in map field. * @return the value of the property, not null */ public ImmutableMap> getMapInMap() { return mapInMap; } //----------------------------------------------------------------------- /** * Gets the simple table. * @return the value of the property */ public ImmutableTable getSimpleTable() { return simpleTable; } //----------------------------------------------------------------------- /** * Gets the compound table. * @return the value of the property */ public ImmutableTable getCompoundTable() { return compoundTable; } //----------------------------------------------------------------------- /** * Gets the grid. * @return the value of the property */ public ImmutableGrid getSparseGrid() { return sparseGrid; } //----------------------------------------------------------------------- /** * Gets the grid. * @return the value of the property */ public ImmutableGrid getDenseGrid() { return denseGrid; } //----------------------------------------------------------------------- /** * Gets the bean key and bean value field. * @return the value of the property, not null */ public ImmutableMap getBeanBeanMap() { return beanBeanMap; } //----------------------------------------------------------------------- /** * Gets the array. * @return the value of the property */ public double[] getDoubleVector() { return (doubleVector != null ? doubleVector.clone() : null); } //----------------------------------------------------------------------- /** * Gets the matrix. * @return the value of the property */ public double[][] getMatrix() { return (double[][]) JodaBeanUtils.cloneArray(matrix); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmAddress other = (ImmAddress) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.city, other.city) && JodaBeanUtils.equal(this.abstractNumber, other.abstractNumber) && JodaBeanUtils.equal(this.data, other.data) && JodaBeanUtils.equal(this.array2d, other.array2d) && JodaBeanUtils.equal(this.owner, other.owner) && JodaBeanUtils.equal(this.object1, other.object1) && JodaBeanUtils.equal(this.object2, other.object2) && JodaBeanUtils.equal(this.risk, other.risk) && JodaBeanUtils.equal(this.riskLevel, other.riskLevel) && JodaBeanUtils.equal(this.riskLevels, other.riskLevels) && JodaBeanUtils.equal(this.serializable, other.serializable) && JodaBeanUtils.equal(this.objectInMap, other.objectInMap) && JodaBeanUtils.equal(this.listInMap, other.listInMap) && JodaBeanUtils.equal(this.listNumericInMap, other.listNumericInMap) && JodaBeanUtils.equal(this.listInListInMap, other.listInListInMap) && JodaBeanUtils.equal(this.objectListInListInMap, other.objectListInListInMap) && JodaBeanUtils.equal(this.mapInMap, other.mapInMap) && JodaBeanUtils.equal(this.simpleTable, other.simpleTable) && JodaBeanUtils.equal(this.compoundTable, other.compoundTable) && JodaBeanUtils.equal(this.sparseGrid, other.sparseGrid) && JodaBeanUtils.equal(this.denseGrid, other.denseGrid) && JodaBeanUtils.equal(this.beanBeanMap, other.beanBeanMap) && JodaBeanUtils.equal(this.doubleVector, other.doubleVector) && JodaBeanUtils.equal(this.matrix, other.matrix); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(city); hash = hash * 31 + JodaBeanUtils.hashCode(abstractNumber); hash = hash * 31 + JodaBeanUtils.hashCode(data); hash = hash * 31 + JodaBeanUtils.hashCode(array2d); hash = hash * 31 + JodaBeanUtils.hashCode(owner); hash = hash * 31 + JodaBeanUtils.hashCode(object1); hash = hash * 31 + JodaBeanUtils.hashCode(object2); hash = hash * 31 + JodaBeanUtils.hashCode(risk); hash = hash * 31 + JodaBeanUtils.hashCode(riskLevel); hash = hash * 31 + JodaBeanUtils.hashCode(riskLevels); hash = hash * 31 + JodaBeanUtils.hashCode(serializable); hash = hash * 31 + JodaBeanUtils.hashCode(objectInMap); hash = hash * 31 + JodaBeanUtils.hashCode(listInMap); hash = hash * 31 + JodaBeanUtils.hashCode(listNumericInMap); hash = hash * 31 + JodaBeanUtils.hashCode(listInListInMap); hash = hash * 31 + JodaBeanUtils.hashCode(objectListInListInMap); hash = hash * 31 + JodaBeanUtils.hashCode(mapInMap); hash = hash * 31 + JodaBeanUtils.hashCode(simpleTable); hash = hash * 31 + JodaBeanUtils.hashCode(compoundTable); hash = hash * 31 + JodaBeanUtils.hashCode(sparseGrid); hash = hash * 31 + JodaBeanUtils.hashCode(denseGrid); hash = hash * 31 + JodaBeanUtils.hashCode(beanBeanMap); hash = hash * 31 + JodaBeanUtils.hashCode(doubleVector); hash = hash * 31 + JodaBeanUtils.hashCode(matrix); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(864); buf.append("ImmAddress{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("abstractNumber").append('=').append(JodaBeanUtils.toString(abstractNumber)).append(',').append(' '); buf.append("data").append('=').append(JodaBeanUtils.toString(data)).append(',').append(' '); buf.append("array2d").append('=').append(JodaBeanUtils.toString(array2d)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)).append(',').append(' '); buf.append("object1").append('=').append(JodaBeanUtils.toString(object1)).append(',').append(' '); buf.append("object2").append('=').append(JodaBeanUtils.toString(object2)).append(',').append(' '); buf.append("risk").append('=').append(JodaBeanUtils.toString(risk)).append(',').append(' '); buf.append("riskLevel").append('=').append(JodaBeanUtils.toString(riskLevel)).append(',').append(' '); buf.append("riskLevels").append('=').append(JodaBeanUtils.toString(riskLevels)).append(',').append(' '); buf.append("serializable").append('=').append(JodaBeanUtils.toString(serializable)).append(',').append(' '); buf.append("objectInMap").append('=').append(JodaBeanUtils.toString(objectInMap)).append(',').append(' '); buf.append("listInMap").append('=').append(JodaBeanUtils.toString(listInMap)).append(',').append(' '); buf.append("listNumericInMap").append('=').append(JodaBeanUtils.toString(listNumericInMap)).append(',').append(' '); buf.append("listInListInMap").append('=').append(JodaBeanUtils.toString(listInListInMap)).append(',').append(' '); buf.append("objectListInListInMap").append('=').append(JodaBeanUtils.toString(objectListInListInMap)).append(',').append(' '); buf.append("mapInMap").append('=').append(JodaBeanUtils.toString(mapInMap)).append(',').append(' '); buf.append("simpleTable").append('=').append(JodaBeanUtils.toString(simpleTable)).append(',').append(' '); buf.append("compoundTable").append('=').append(JodaBeanUtils.toString(compoundTable)).append(',').append(' '); buf.append("sparseGrid").append('=').append(JodaBeanUtils.toString(sparseGrid)).append(',').append(' '); buf.append("denseGrid").append('=').append(JodaBeanUtils.toString(denseGrid)).append(',').append(' '); buf.append("beanBeanMap").append('=').append(JodaBeanUtils.toString(beanBeanMap)).append(',').append(' '); buf.append("doubleVector").append('=').append(JodaBeanUtils.toString(doubleVector)).append(',').append(' '); buf.append("matrix").append('=').append(JodaBeanUtils.toString(matrix)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmAddress}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code number} property. */ private final MetaProperty number = DirectMetaProperty.ofImmutable( this, "number", ImmAddress.class, Integer.TYPE); /** * The meta-property for the {@code street} property. */ private final MetaProperty street = DirectMetaProperty.ofImmutable( this, "street", ImmAddress.class, String.class); /** * The meta-property for the {@code city} property. */ private final MetaProperty city = DirectMetaProperty.ofImmutable( this, "city", ImmAddress.class, String.class); /** * The meta-property for the {@code abstractNumber} property. */ private final MetaProperty abstractNumber = DirectMetaProperty.ofImmutable( this, "abstractNumber", ImmAddress.class, Number.class); /** * The meta-property for the {@code data} property. */ private final MetaProperty data = DirectMetaProperty.ofImmutable( this, "data", ImmAddress.class, byte[].class); /** * The meta-property for the {@code array2d} property. */ private final MetaProperty array2d = DirectMetaProperty.ofImmutable( this, "array2d", ImmAddress.class, String[][].class); /** * The meta-property for the {@code owner} property. */ private final MetaProperty owner = DirectMetaProperty.ofImmutable( this, "owner", ImmAddress.class, ImmPerson.class); /** * The meta-property for the {@code object1} property. */ private final MetaProperty object1 = DirectMetaProperty.ofImmutable( this, "object1", ImmAddress.class, Object.class); /** * The meta-property for the {@code object2} property. */ private final MetaProperty object2 = DirectMetaProperty.ofImmutable( this, "object2", ImmAddress.class, Object.class); /** * The meta-property for the {@code risk} property. */ private final MetaProperty risk = DirectMetaProperty.ofImmutable( this, "risk", ImmAddress.class, Risk.class); /** * The meta-property for the {@code riskLevel} property. */ private final MetaProperty riskLevel = DirectMetaProperty.ofImmutable( this, "riskLevel", ImmAddress.class, RiskLevel.class); /** * The meta-property for the {@code riskLevels} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> riskLevels = DirectMetaProperty.ofImmutable( this, "riskLevels", ImmAddress.class, (Class) EnumSet.class); /** * The meta-property for the {@code serializable} property. */ private final MetaProperty serializable = DirectMetaProperty.ofImmutable( this, "serializable", ImmAddress.class, Serializable.class); /** * The meta-property for the {@code objectInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> objectInMap = DirectMetaProperty.ofImmutable( this, "objectInMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code listInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> listInMap = DirectMetaProperty.ofImmutable( this, "listInMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code listNumericInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> listNumericInMap = DirectMetaProperty.ofImmutable( this, "listNumericInMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code listInListInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>>> listInListInMap = DirectMetaProperty.ofImmutable( this, "listInListInMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code objectListInListInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>>> objectListInListInMap = DirectMetaProperty.ofImmutable( this, "objectListInListInMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code mapInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> mapInMap = DirectMetaProperty.ofImmutable( this, "mapInMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code simpleTable} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> simpleTable = DirectMetaProperty.ofImmutable( this, "simpleTable", ImmAddress.class, (Class) ImmutableTable.class); /** * The meta-property for the {@code compoundTable} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> compoundTable = DirectMetaProperty.ofImmutable( this, "compoundTable", ImmAddress.class, (Class) ImmutableTable.class); /** * The meta-property for the {@code sparseGrid} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sparseGrid = DirectMetaProperty.ofImmutable( this, "sparseGrid", ImmAddress.class, (Class) ImmutableGrid.class); /** * The meta-property for the {@code denseGrid} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> denseGrid = DirectMetaProperty.ofImmutable( this, "denseGrid", ImmAddress.class, (Class) ImmutableGrid.class); /** * The meta-property for the {@code beanBeanMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> beanBeanMap = DirectMetaProperty.ofImmutable( this, "beanBeanMap", ImmAddress.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code doubleVector} property. */ private final MetaProperty doubleVector = DirectMetaProperty.ofImmutable( this, "doubleVector", ImmAddress.class, double[].class); /** * The meta-property for the {@code matrix} property. */ private final MetaProperty matrix = DirectMetaProperty.ofImmutable( this, "matrix", ImmAddress.class, double[][].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "number", "street", "city", "abstractNumber", "data", "array2d", "owner", "object1", "object2", "risk", "riskLevel", "riskLevels", "serializable", "objectInMap", "listInMap", "listNumericInMap", "listInListInMap", "objectListInListInMap", "mapInMap", "simpleTable", "compoundTable", "sparseGrid", "denseGrid", "beanBeanMap", "doubleVector", "matrix"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 1986500107: // abstractNumber return this.abstractNumber; case 3076010: // data return this.data; case -734443893: // array2d return this.array2d; case 106164915: // owner return this.owner; case -1659648814: // object1 return this.object1; case -1659648813: // object2 return this.object2; case 3500751: // risk return this.risk; case 540453365: // riskLevel return this.riskLevel; case -425814754: // riskLevels return this.riskLevels; case 861034751: // serializable return this.serializable; case -1297715720: // objectInMap return this.objectInMap; case -1244601351: // listInMap return this.listInMap; case 391098024: // listNumericInMap return this.listNumericInMap; case -940836650: // listInListInMap return this.listInListInMap; case -861321321: // objectListInListInMap return this.objectListInListInMap; case 158545403: // mapInMap return this.mapInMap; case -1429579460: // simpleTable return this.simpleTable; case 103339235: // compoundTable return this.compoundTable; case 1337284998: // sparseGrid return this.sparseGrid; case 1802377989: // denseGrid return this.denseGrid; case -2039203396: // beanBeanMap return this.beanBeanMap; case 1118070900: // doubleVector return this.doubleVector; case -1081239615: // matrix return this.matrix; } return super.metaPropertyGet(propertyName); } @Override public ImmAddress.Builder builder() { return new ImmAddress.Builder(); } @Override public Class beanType() { return ImmAddress.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code number} property. * @return the meta-property, not null */ public MetaProperty number() { return number; } /** * The meta-property for the {@code street} property. * @return the meta-property, not null */ public MetaProperty street() { return street; } /** * The meta-property for the {@code city} property. * @return the meta-property, not null */ public MetaProperty city() { return city; } /** * The meta-property for the {@code abstractNumber} property. * @return the meta-property, not null */ public MetaProperty abstractNumber() { return abstractNumber; } /** * The meta-property for the {@code data} property. * @return the meta-property, not null */ public MetaProperty data() { return data; } /** * The meta-property for the {@code array2d} property. * @return the meta-property, not null */ public MetaProperty array2d() { return array2d; } /** * The meta-property for the {@code owner} property. * @return the meta-property, not null */ public MetaProperty owner() { return owner; } /** * The meta-property for the {@code object1} property. * @return the meta-property, not null */ public MetaProperty object1() { return object1; } /** * The meta-property for the {@code object2} property. * @return the meta-property, not null */ public MetaProperty object2() { return object2; } /** * The meta-property for the {@code risk} property. * @return the meta-property, not null */ public MetaProperty risk() { return risk; } /** * The meta-property for the {@code riskLevel} property. * @return the meta-property, not null */ public MetaProperty riskLevel() { return riskLevel; } /** * The meta-property for the {@code riskLevels} property. * @return the meta-property, not null */ public MetaProperty> riskLevels() { return riskLevels; } /** * The meta-property for the {@code serializable} property. * @return the meta-property, not null */ public MetaProperty serializable() { return serializable; } /** * The meta-property for the {@code objectInMap} property. * @return the meta-property, not null */ public MetaProperty> objectInMap() { return objectInMap; } /** * The meta-property for the {@code listInMap} property. * @return the meta-property, not null */ public MetaProperty>> listInMap() { return listInMap; } /** * The meta-property for the {@code listNumericInMap} property. * @return the meta-property, not null */ public MetaProperty>> listNumericInMap() { return listNumericInMap; } /** * The meta-property for the {@code listInListInMap} property. * @return the meta-property, not null */ public MetaProperty>>> listInListInMap() { return listInListInMap; } /** * The meta-property for the {@code objectListInListInMap} property. * @return the meta-property, not null */ public MetaProperty>>> objectListInListInMap() { return objectListInListInMap; } /** * The meta-property for the {@code mapInMap} property. * @return the meta-property, not null */ public MetaProperty>> mapInMap() { return mapInMap; } /** * The meta-property for the {@code simpleTable} property. * @return the meta-property, not null */ public MetaProperty> simpleTable() { return simpleTable; } /** * The meta-property for the {@code compoundTable} property. * @return the meta-property, not null */ public MetaProperty> compoundTable() { return compoundTable; } /** * The meta-property for the {@code sparseGrid} property. * @return the meta-property, not null */ public MetaProperty> sparseGrid() { return sparseGrid; } /** * The meta-property for the {@code denseGrid} property. * @return the meta-property, not null */ public MetaProperty> denseGrid() { return denseGrid; } /** * The meta-property for the {@code beanBeanMap} property. * @return the meta-property, not null */ public MetaProperty> beanBeanMap() { return beanBeanMap; } /** * The meta-property for the {@code doubleVector} property. * @return the meta-property, not null */ public MetaProperty doubleVector() { return doubleVector; } /** * The meta-property for the {@code matrix} property. * @return the meta-property, not null */ public MetaProperty matrix() { return matrix; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1034364087: // number return ((ImmAddress) bean).getNumber(); case -891990013: // street return ((ImmAddress) bean).getStreet(); case 3053931: // city return ((ImmAddress) bean).getCity(); case 1986500107: // abstractNumber return ((ImmAddress) bean).getAbstractNumber(); case 3076010: // data return ((ImmAddress) bean).getData(); case -734443893: // array2d return ((ImmAddress) bean).getArray2d(); case 106164915: // owner return ((ImmAddress) bean).getOwner(); case -1659648814: // object1 return ((ImmAddress) bean).getObject1(); case -1659648813: // object2 return ((ImmAddress) bean).getObject2(); case 3500751: // risk return ((ImmAddress) bean).getRisk(); case 540453365: // riskLevel return ((ImmAddress) bean).getRiskLevel(); case -425814754: // riskLevels return ((ImmAddress) bean).getRiskLevels(); case 861034751: // serializable return ((ImmAddress) bean).getSerializable(); case -1297715720: // objectInMap return ((ImmAddress) bean).getObjectInMap(); case -1244601351: // listInMap return ((ImmAddress) bean).getListInMap(); case 391098024: // listNumericInMap return ((ImmAddress) bean).getListNumericInMap(); case -940836650: // listInListInMap return ((ImmAddress) bean).getListInListInMap(); case -861321321: // objectListInListInMap return ((ImmAddress) bean).getObjectListInListInMap(); case 158545403: // mapInMap return ((ImmAddress) bean).getMapInMap(); case -1429579460: // simpleTable return ((ImmAddress) bean).getSimpleTable(); case 103339235: // compoundTable return ((ImmAddress) bean).getCompoundTable(); case 1337284998: // sparseGrid return ((ImmAddress) bean).getSparseGrid(); case 1802377989: // denseGrid return ((ImmAddress) bean).getDenseGrid(); case -2039203396: // beanBeanMap return ((ImmAddress) bean).getBeanBeanMap(); case 1118070900: // doubleVector return ((ImmAddress) bean).getDoubleVector(); case -1081239615: // matrix return ((ImmAddress) bean).getMatrix(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmAddress}. */ public static final class Builder extends DirectFieldsBeanBuilder { private int number; private String street; private String city; private Number abstractNumber; private byte[] data; private String[][] array2d; private ImmPerson owner; private Object object1; private Object object2; private Risk risk; private RiskLevel riskLevel; private Set riskLevels; private Serializable serializable; private Map objectInMap = ImmutableMap.of(); private Map> listInMap = ImmutableMap.of(); private Map> listNumericInMap = ImmutableMap.of(); private Map>> listInListInMap = ImmutableMap.of(); private Map>> objectListInListInMap = ImmutableMap.of(); private Map> mapInMap = ImmutableMap.of(); private Table simpleTable; private Table compoundTable; private Grid sparseGrid; private Grid denseGrid; private Map beanBeanMap = ImmutableMap.of(); private double[] doubleVector; private double[][] matrix; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmAddress beanToCopy) { this.number = beanToCopy.getNumber(); this.street = beanToCopy.getStreet(); this.city = beanToCopy.getCity(); this.abstractNumber = beanToCopy.getAbstractNumber(); this.data = (beanToCopy.getData() != null ? beanToCopy.getData().clone() : null); this.array2d = (String[][]) JodaBeanUtils.cloneArray(beanToCopy.getArray2d()); this.owner = beanToCopy.getOwner(); this.object1 = beanToCopy.getObject1(); this.object2 = beanToCopy.getObject2(); this.risk = beanToCopy.getRisk(); this.riskLevel = beanToCopy.getRiskLevel(); this.riskLevels = (beanToCopy.getRiskLevels() != null ? new HashSet<>(beanToCopy.getRiskLevels()) : null); this.serializable = beanToCopy.getSerializable(); this.objectInMap = beanToCopy.getObjectInMap(); this.listInMap = beanToCopy.getListInMap(); this.listNumericInMap = beanToCopy.getListNumericInMap(); this.listInListInMap = beanToCopy.getListInListInMap(); this.objectListInListInMap = beanToCopy.getObjectListInListInMap(); this.mapInMap = beanToCopy.getMapInMap(); this.simpleTable = beanToCopy.getSimpleTable(); this.compoundTable = beanToCopy.getCompoundTable(); this.sparseGrid = beanToCopy.getSparseGrid(); this.denseGrid = beanToCopy.getDenseGrid(); this.beanBeanMap = beanToCopy.getBeanBeanMap(); this.doubleVector = (beanToCopy.getDoubleVector() != null ? beanToCopy.getDoubleVector().clone() : null); this.matrix = (double[][]) JodaBeanUtils.cloneArray(beanToCopy.getMatrix()); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 1986500107: // abstractNumber return this.abstractNumber; case 3076010: // data return this.data; case -734443893: // array2d return this.array2d; case 106164915: // owner return this.owner; case -1659648814: // object1 return this.object1; case -1659648813: // object2 return this.object2; case 3500751: // risk return this.risk; case 540453365: // riskLevel return this.riskLevel; case -425814754: // riskLevels return this.riskLevels; case 861034751: // serializable return this.serializable; case -1297715720: // objectInMap return this.objectInMap; case -1244601351: // listInMap return this.listInMap; case 391098024: // listNumericInMap return this.listNumericInMap; case -940836650: // listInListInMap return this.listInListInMap; case -861321321: // objectListInListInMap return this.objectListInListInMap; case 158545403: // mapInMap return this.mapInMap; case -1429579460: // simpleTable return this.simpleTable; case 103339235: // compoundTable return this.compoundTable; case 1337284998: // sparseGrid return this.sparseGrid; case 1802377989: // denseGrid return this.denseGrid; case -2039203396: // beanBeanMap return this.beanBeanMap; case 1118070900: // doubleVector return this.doubleVector; case -1081239615: // matrix return this.matrix; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (Integer) newValue; break; case -891990013: // street this.street = (String) newValue; break; case 3053931: // city this.city = (String) newValue; break; case 1986500107: // abstractNumber this.abstractNumber = (Number) newValue; break; case 3076010: // data this.data = (byte[]) newValue; break; case -734443893: // array2d this.array2d = (String[][]) newValue; break; case 106164915: // owner this.owner = (ImmPerson) newValue; break; case -1659648814: // object1 this.object1 = (Object) newValue; break; case -1659648813: // object2 this.object2 = (Object) newValue; break; case 3500751: // risk this.risk = (Risk) newValue; break; case 540453365: // riskLevel this.riskLevel = (RiskLevel) newValue; break; case -425814754: // riskLevels this.riskLevels = (Set) newValue; break; case 861034751: // serializable this.serializable = (Serializable) newValue; break; case -1297715720: // objectInMap this.objectInMap = (Map) newValue; break; case -1244601351: // listInMap this.listInMap = (Map>) newValue; break; case 391098024: // listNumericInMap this.listNumericInMap = (Map>) newValue; break; case -940836650: // listInListInMap this.listInListInMap = (Map>>) newValue; break; case -861321321: // objectListInListInMap this.objectListInListInMap = (Map>>) newValue; break; case 158545403: // mapInMap this.mapInMap = (Map>) newValue; break; case -1429579460: // simpleTable this.simpleTable = (Table) newValue; break; case 103339235: // compoundTable this.compoundTable = (Table) newValue; break; case 1337284998: // sparseGrid this.sparseGrid = (Grid) newValue; break; case 1802377989: // denseGrid this.denseGrid = (Grid) newValue; break; case -2039203396: // beanBeanMap this.beanBeanMap = (Map) newValue; break; case 1118070900: // doubleVector this.doubleVector = (double[]) newValue; break; case -1081239615: // matrix this.matrix = (double[][]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmAddress build() { return new ImmAddress( number, street, city, abstractNumber, data, array2d, owner, object1, object2, risk, riskLevel, riskLevels, serializable, objectInMap, listInMap, listNumericInMap, listInListInMap, objectListInListInMap, mapInMap, simpleTable, compoundTable, sparseGrid, denseGrid, beanBeanMap, doubleVector, matrix); } //----------------------------------------------------------------------- /** * Sets the number. * This will be the flat, house number or house name. * @param number the new value * @return this, for chaining, not null */ public Builder number(int number) { this.number = number; return this; } /** * Sets the street. * @param street the new value, not null * @return this, for chaining, not null */ public Builder street(String street) { JodaBeanUtils.notNull(street, "street"); this.street = street; return this; } /** * Sets the city. * @param city the new value, not null * @return this, for chaining, not null */ public Builder city(String city) { JodaBeanUtils.notNull(city, "city"); this.city = city; return this; } /** * Sets the abstract number. * @param abstractNumber the new value * @return this, for chaining, not null */ public Builder abstractNumber(Number abstractNumber) { this.abstractNumber = abstractNumber; return this; } /** * Sets the extra data. * @param data the new value * @return this, for chaining, not null */ public Builder data(byte[] data) { this.data = data; return this; } /** * Sets the 2D array. * @param array2d the new value * @return this, for chaining, not null */ public Builder array2d(String[][] array2d) { this.array2d = array2d; return this; } /** * Sets the owner. * @param owner the new value, not null * @return this, for chaining, not null */ public Builder owner(ImmPerson owner) { JodaBeanUtils.notNull(owner, "owner"); this.owner = owner; return this; } /** * Sets the object field. * @param object1 the new value * @return this, for chaining, not null */ public Builder object1(Object object1) { this.object1 = object1; return this; } /** * Sets the object field. * @param object2 the new value * @return this, for chaining, not null */ public Builder object2(Object object2) { this.object2 = object2; return this; } /** * Sets the risk field. * @param risk the new value * @return this, for chaining, not null */ public Builder risk(Risk risk) { this.risk = risk; return this; } /** * Sets the risk level field, testing an {@code Enum}. * @param riskLevel the new value * @return this, for chaining, not null */ public Builder riskLevel(RiskLevel riskLevel) { this.riskLevel = riskLevel; return this; } /** * Sets the risk levels field, testing {@code EnumSet}. * @param riskLevels the new value * @return this, for chaining, not null */ public Builder riskLevels(Set riskLevels) { this.riskLevels = riskLevels; return this; } /** * Sets the {@code riskLevels} property in the builder * from an array of objects. * @param riskLevels the new value * @return this, for chaining, not null */ public Builder riskLevels(RiskLevel... riskLevels) { return riskLevels(EnumSet.copyOf(Arrays.asList(riskLevels))); } /** * Sets the serializable field. * @param serializable the new value * @return this, for chaining, not null */ public Builder serializable(Serializable serializable) { this.serializable = serializable; return this; } /** * Sets the object in map field. * @param objectInMap the new value, not null * @return this, for chaining, not null */ public Builder objectInMap(Map objectInMap) { JodaBeanUtils.notNull(objectInMap, "objectInMap"); this.objectInMap = objectInMap; return this; } /** * Sets the list in map field. * @param listInMap the new value, not null * @return this, for chaining, not null */ public Builder listInMap(Map> listInMap) { JodaBeanUtils.notNull(listInMap, "listInMap"); this.listInMap = listInMap; return this; } /** * Sets the list in map field. * @param listNumericInMap the new value, not null * @return this, for chaining, not null */ public Builder listNumericInMap(Map> listNumericInMap) { JodaBeanUtils.notNull(listNumericInMap, "listNumericInMap"); this.listNumericInMap = listNumericInMap; return this; } /** * Sets the list in list in map field. * @param listInListInMap the new value, not null * @return this, for chaining, not null */ public Builder listInListInMap(Map>> listInListInMap) { JodaBeanUtils.notNull(listInListInMap, "listInListInMap"); this.listInListInMap = listInListInMap; return this; } /** * Sets the object list in list in map field. * @param objectListInListInMap the new value, not null * @return this, for chaining, not null */ public Builder objectListInListInMap(Map>> objectListInListInMap) { JodaBeanUtils.notNull(objectListInListInMap, "objectListInListInMap"); this.objectListInListInMap = objectListInListInMap; return this; } /** * Sets the map in map field. * @param mapInMap the new value, not null * @return this, for chaining, not null */ public Builder mapInMap(Map> mapInMap) { JodaBeanUtils.notNull(mapInMap, "mapInMap"); this.mapInMap = mapInMap; return this; } /** * Sets the simple table. * @param simpleTable the new value * @return this, for chaining, not null */ public Builder simpleTable(Table simpleTable) { this.simpleTable = simpleTable; return this; } /** * Sets the compound table. * @param compoundTable the new value * @return this, for chaining, not null */ public Builder compoundTable(Table compoundTable) { this.compoundTable = compoundTable; return this; } /** * Sets the grid. * @param sparseGrid the new value * @return this, for chaining, not null */ public Builder sparseGrid(Grid sparseGrid) { this.sparseGrid = sparseGrid; return this; } /** * Sets the grid. * @param denseGrid the new value * @return this, for chaining, not null */ public Builder denseGrid(Grid denseGrid) { this.denseGrid = denseGrid; return this; } /** * Sets the bean key and bean value field. * @param beanBeanMap the new value, not null * @return this, for chaining, not null */ public Builder beanBeanMap(Map beanBeanMap) { JodaBeanUtils.notNull(beanBeanMap, "beanBeanMap"); this.beanBeanMap = beanBeanMap; return this; } /** * Sets the array. * @param doubleVector the new value * @return this, for chaining, not null */ public Builder doubleVector(double... doubleVector) { this.doubleVector = doubleVector; return this; } /** * Sets the matrix. * @param matrix the new value * @return this, for chaining, not null */ public Builder matrix(double[][] matrix) { this.matrix = matrix; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(864); buf.append("ImmAddress.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("abstractNumber").append('=').append(JodaBeanUtils.toString(abstractNumber)).append(',').append(' '); buf.append("data").append('=').append(JodaBeanUtils.toString(data)).append(',').append(' '); buf.append("array2d").append('=').append(JodaBeanUtils.toString(array2d)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)).append(',').append(' '); buf.append("object1").append('=').append(JodaBeanUtils.toString(object1)).append(',').append(' '); buf.append("object2").append('=').append(JodaBeanUtils.toString(object2)).append(',').append(' '); buf.append("risk").append('=').append(JodaBeanUtils.toString(risk)).append(',').append(' '); buf.append("riskLevel").append('=').append(JodaBeanUtils.toString(riskLevel)).append(',').append(' '); buf.append("riskLevels").append('=').append(JodaBeanUtils.toString(riskLevels)).append(',').append(' '); buf.append("serializable").append('=').append(JodaBeanUtils.toString(serializable)).append(',').append(' '); buf.append("objectInMap").append('=').append(JodaBeanUtils.toString(objectInMap)).append(',').append(' '); buf.append("listInMap").append('=').append(JodaBeanUtils.toString(listInMap)).append(',').append(' '); buf.append("listNumericInMap").append('=').append(JodaBeanUtils.toString(listNumericInMap)).append(',').append(' '); buf.append("listInListInMap").append('=').append(JodaBeanUtils.toString(listInListInMap)).append(',').append(' '); buf.append("objectListInListInMap").append('=').append(JodaBeanUtils.toString(objectListInListInMap)).append(',').append(' '); buf.append("mapInMap").append('=').append(JodaBeanUtils.toString(mapInMap)).append(',').append(' '); buf.append("simpleTable").append('=').append(JodaBeanUtils.toString(simpleTable)).append(',').append(' '); buf.append("compoundTable").append('=').append(JodaBeanUtils.toString(compoundTable)).append(',').append(' '); buf.append("sparseGrid").append('=').append(JodaBeanUtils.toString(sparseGrid)).append(',').append(' '); buf.append("denseGrid").append('=').append(JodaBeanUtils.toString(denseGrid)).append(',').append(' '); buf.append("beanBeanMap").append('=').append(JodaBeanUtils.toString(beanBeanMap)).append(',').append(' '); buf.append("doubleVector").append('=').append(JodaBeanUtils.toString(doubleVector)).append(',').append(' '); buf.append("matrix").append('=').append(JodaBeanUtils.toString(matrix)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmArrays.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock bean for primitive array testing. * * @author Stephen Colebourne */ @BeanDefinition(factoryName = "of") public final class ImmArrays implements ImmutableBean { @PropertyDefinition private final int[] intArray; @PropertyDefinition private final long[] longArray; @PropertyDefinition private final double[] doubleArray; @PropertyDefinition private final boolean[] booleanArray; @PropertyDefinition private final int[][] intArray2d; @PropertyDefinition private final boolean[][] booleanArray2d; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmArrays}. * @return the meta-bean, not null */ public static ImmArrays.Meta meta() { return ImmArrays.Meta.INSTANCE; } static { MetaBean.register(ImmArrays.Meta.INSTANCE); } /** * Obtains an instance. * @param intArray the value of the property * @param longArray the value of the property * @param doubleArray the value of the property * @param booleanArray the value of the property * @param intArray2d the value of the property * @param booleanArray2d the value of the property * @return the instance */ public static ImmArrays of( int[] intArray, long[] longArray, double[] doubleArray, boolean[] booleanArray, int[][] intArray2d, boolean[][] booleanArray2d) { return new ImmArrays( intArray, longArray, doubleArray, booleanArray, intArray2d, booleanArray2d); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmArrays.Builder builder() { return new ImmArrays.Builder(); } private ImmArrays( int[] intArray, long[] longArray, double[] doubleArray, boolean[] booleanArray, int[][] intArray2d, boolean[][] booleanArray2d) { this.intArray = (intArray != null ? intArray.clone() : null); this.longArray = (longArray != null ? longArray.clone() : null); this.doubleArray = (doubleArray != null ? doubleArray.clone() : null); this.booleanArray = (booleanArray != null ? booleanArray.clone() : null); this.intArray2d = (int[][]) JodaBeanUtils.cloneArray(intArray2d); this.booleanArray2d = (boolean[][]) JodaBeanUtils.cloneArray(booleanArray2d); } @Override public ImmArrays.Meta metaBean() { return ImmArrays.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the intArray. * @return the value of the property */ public int[] getIntArray() { return (intArray != null ? intArray.clone() : null); } //----------------------------------------------------------------------- /** * Gets the longArray. * @return the value of the property */ public long[] getLongArray() { return (longArray != null ? longArray.clone() : null); } //----------------------------------------------------------------------- /** * Gets the doubleArray. * @return the value of the property */ public double[] getDoubleArray() { return (doubleArray != null ? doubleArray.clone() : null); } //----------------------------------------------------------------------- /** * Gets the booleanArray. * @return the value of the property */ public boolean[] getBooleanArray() { return (booleanArray != null ? booleanArray.clone() : null); } //----------------------------------------------------------------------- /** * Gets the intArray2d. * @return the value of the property */ public int[][] getIntArray2d() { return (int[][]) JodaBeanUtils.cloneArray(intArray2d); } //----------------------------------------------------------------------- /** * Gets the booleanArray2d. * @return the value of the property */ public boolean[][] getBooleanArray2d() { return (boolean[][]) JodaBeanUtils.cloneArray(booleanArray2d); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmArrays other = (ImmArrays) obj; return JodaBeanUtils.equal(this.intArray, other.intArray) && JodaBeanUtils.equal(this.longArray, other.longArray) && JodaBeanUtils.equal(this.doubleArray, other.doubleArray) && JodaBeanUtils.equal(this.booleanArray, other.booleanArray) && JodaBeanUtils.equal(this.intArray2d, other.intArray2d) && JodaBeanUtils.equal(this.booleanArray2d, other.booleanArray2d); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(intArray); hash = hash * 31 + JodaBeanUtils.hashCode(longArray); hash = hash * 31 + JodaBeanUtils.hashCode(doubleArray); hash = hash * 31 + JodaBeanUtils.hashCode(booleanArray); hash = hash * 31 + JodaBeanUtils.hashCode(intArray2d); hash = hash * 31 + JodaBeanUtils.hashCode(booleanArray2d); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("ImmArrays{"); buf.append("intArray").append('=').append(JodaBeanUtils.toString(intArray)).append(',').append(' '); buf.append("longArray").append('=').append(JodaBeanUtils.toString(longArray)).append(',').append(' '); buf.append("doubleArray").append('=').append(JodaBeanUtils.toString(doubleArray)).append(',').append(' '); buf.append("booleanArray").append('=').append(JodaBeanUtils.toString(booleanArray)).append(',').append(' '); buf.append("intArray2d").append('=').append(JodaBeanUtils.toString(intArray2d)).append(',').append(' '); buf.append("booleanArray2d").append('=').append(JodaBeanUtils.toString(booleanArray2d)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmArrays}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code intArray} property. */ private final MetaProperty intArray = DirectMetaProperty.ofImmutable( this, "intArray", ImmArrays.class, int[].class); /** * The meta-property for the {@code longArray} property. */ private final MetaProperty longArray = DirectMetaProperty.ofImmutable( this, "longArray", ImmArrays.class, long[].class); /** * The meta-property for the {@code doubleArray} property. */ private final MetaProperty doubleArray = DirectMetaProperty.ofImmutable( this, "doubleArray", ImmArrays.class, double[].class); /** * The meta-property for the {@code booleanArray} property. */ private final MetaProperty booleanArray = DirectMetaProperty.ofImmutable( this, "booleanArray", ImmArrays.class, boolean[].class); /** * The meta-property for the {@code intArray2d} property. */ private final MetaProperty intArray2d = DirectMetaProperty.ofImmutable( this, "intArray2d", ImmArrays.class, int[][].class); /** * The meta-property for the {@code booleanArray2d} property. */ private final MetaProperty booleanArray2d = DirectMetaProperty.ofImmutable( this, "booleanArray2d", ImmArrays.class, boolean[][].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "intArray", "longArray", "doubleArray", "booleanArray", "intArray2d", "booleanArray2d"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 537167786: // intArray return this.intArray; case 100362557: // longArray return this.longArray; case -1645494008: // doubleArray return this.doubleArray; case -1066176751: // booleanArray return this.booleanArray; case 822168476: // intArray2d return this.intArray2d; case 1901327683: // booleanArray2d return this.booleanArray2d; } return super.metaPropertyGet(propertyName); } @Override public ImmArrays.Builder builder() { return new ImmArrays.Builder(); } @Override public Class beanType() { return ImmArrays.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code intArray} property. * @return the meta-property, not null */ public MetaProperty intArray() { return intArray; } /** * The meta-property for the {@code longArray} property. * @return the meta-property, not null */ public MetaProperty longArray() { return longArray; } /** * The meta-property for the {@code doubleArray} property. * @return the meta-property, not null */ public MetaProperty doubleArray() { return doubleArray; } /** * The meta-property for the {@code booleanArray} property. * @return the meta-property, not null */ public MetaProperty booleanArray() { return booleanArray; } /** * The meta-property for the {@code intArray2d} property. * @return the meta-property, not null */ public MetaProperty intArray2d() { return intArray2d; } /** * The meta-property for the {@code booleanArray2d} property. * @return the meta-property, not null */ public MetaProperty booleanArray2d() { return booleanArray2d; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 537167786: // intArray return ((ImmArrays) bean).getIntArray(); case 100362557: // longArray return ((ImmArrays) bean).getLongArray(); case -1645494008: // doubleArray return ((ImmArrays) bean).getDoubleArray(); case -1066176751: // booleanArray return ((ImmArrays) bean).getBooleanArray(); case 822168476: // intArray2d return ((ImmArrays) bean).getIntArray2d(); case 1901327683: // booleanArray2d return ((ImmArrays) bean).getBooleanArray2d(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmArrays}. */ public static final class Builder extends DirectFieldsBeanBuilder { private int[] intArray; private long[] longArray; private double[] doubleArray; private boolean[] booleanArray; private int[][] intArray2d; private boolean[][] booleanArray2d; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmArrays beanToCopy) { this.intArray = (beanToCopy.getIntArray() != null ? beanToCopy.getIntArray().clone() : null); this.longArray = (beanToCopy.getLongArray() != null ? beanToCopy.getLongArray().clone() : null); this.doubleArray = (beanToCopy.getDoubleArray() != null ? beanToCopy.getDoubleArray().clone() : null); this.booleanArray = (beanToCopy.getBooleanArray() != null ? beanToCopy.getBooleanArray().clone() : null); this.intArray2d = (int[][]) JodaBeanUtils.cloneArray(beanToCopy.getIntArray2d()); this.booleanArray2d = (boolean[][]) JodaBeanUtils.cloneArray(beanToCopy.getBooleanArray2d()); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 537167786: // intArray return this.intArray; case 100362557: // longArray return this.longArray; case -1645494008: // doubleArray return this.doubleArray; case -1066176751: // booleanArray return this.booleanArray; case 822168476: // intArray2d return this.intArray2d; case 1901327683: // booleanArray2d return this.booleanArray2d; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 537167786: // intArray this.intArray = (int[]) newValue; break; case 100362557: // longArray this.longArray = (long[]) newValue; break; case -1645494008: // doubleArray this.doubleArray = (double[]) newValue; break; case -1066176751: // booleanArray this.booleanArray = (boolean[]) newValue; break; case 822168476: // intArray2d this.intArray2d = (int[][]) newValue; break; case 1901327683: // booleanArray2d this.booleanArray2d = (boolean[][]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmArrays build() { return new ImmArrays( intArray, longArray, doubleArray, booleanArray, intArray2d, booleanArray2d); } //----------------------------------------------------------------------- /** * Sets the intArray. * @param intArray the new value * @return this, for chaining, not null */ public Builder intArray(int... intArray) { this.intArray = intArray; return this; } /** * Sets the longArray. * @param longArray the new value * @return this, for chaining, not null */ public Builder longArray(long... longArray) { this.longArray = longArray; return this; } /** * Sets the doubleArray. * @param doubleArray the new value * @return this, for chaining, not null */ public Builder doubleArray(double... doubleArray) { this.doubleArray = doubleArray; return this; } /** * Sets the booleanArray. * @param booleanArray the new value * @return this, for chaining, not null */ public Builder booleanArray(boolean... booleanArray) { this.booleanArray = booleanArray; return this; } /** * Sets the intArray2d. * @param intArray2d the new value * @return this, for chaining, not null */ public Builder intArray2d(int[][] intArray2d) { this.intArray2d = intArray2d; return this; } /** * Sets the booleanArray2d. * @param booleanArray2d the new value * @return this, for chaining, not null */ public Builder booleanArray2d(boolean[][] booleanArray2d) { this.booleanArray2d = booleanArray2d; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("ImmArrays.Builder{"); buf.append("intArray").append('=').append(JodaBeanUtils.toString(intArray)).append(',').append(' '); buf.append("longArray").append('=').append(JodaBeanUtils.toString(longArray)).append(',').append(' '); buf.append("doubleArray").append('=').append(JodaBeanUtils.toString(doubleArray)).append(',').append(' '); buf.append("booleanArray").append('=').append(JodaBeanUtils.toString(booleanArray)).append(',').append(' '); buf.append("intArray2d").append('=').append(JodaBeanUtils.toString(intArray2d)).append(',').append(' '); buf.append("booleanArray2d").append('=').append(JodaBeanUtils.toString(booleanArray2d)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmClone.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Date; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock immutable bean to test cloning. * * @author Stephen Colebourne */ @BeanDefinition public final class ImmClone implements ImmutableBean, Serializable{ // NOTE: no space between Serializable and { // clone non-null @PropertyDefinition(validate = "notNull") private final Date date; @PropertyDefinition(validate = "notNull") private final String[] array1; @PropertyDefinition(validate = "notNull", get = "clone") private final String[] array2; @PropertyDefinition(validate = "notNull", get = "cloneCast") private final String[] array3; // clone nuallable @PropertyDefinition() private final Date dateNullable; @PropertyDefinition() private final String[] array1Nullable; @PropertyDefinition(get = "cloneCast") private final String[] array2Nullable; @PropertyDefinition(get = "clone") private final String[] array3Nullable; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmClone}. * @return the meta-bean, not null */ public static ImmClone.Meta meta() { return ImmClone.Meta.INSTANCE; } static { MetaBean.register(ImmClone.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmClone.Builder builder() { return new ImmClone.Builder(); } private ImmClone( Date date, String[] array1, String[] array2, String[] array3, Date dateNullable, String[] array1Nullable, String[] array2Nullable, String[] array3Nullable) { JodaBeanUtils.notNull(date, "date"); JodaBeanUtils.notNull(array1, "array1"); JodaBeanUtils.notNull(array2, "array2"); JodaBeanUtils.notNull(array3, "array3"); this.date = (Date) date.clone(); this.array1 = array1.clone(); this.array2 = array2.clone(); this.array3 = array3.clone(); this.dateNullable = (dateNullable != null ? (Date) dateNullable.clone() : null); this.array1Nullable = (array1Nullable != null ? array1Nullable.clone() : null); this.array2Nullable = (array2Nullable != null ? array2Nullable.clone() : null); this.array3Nullable = (array3Nullable != null ? array3Nullable.clone() : null); } @Override public ImmClone.Meta metaBean() { return ImmClone.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the date. * @return the value of the property, not null */ public Date getDate() { return (Date) date.clone(); } //----------------------------------------------------------------------- /** * Gets the array1. * @return the value of the property, not null */ public String[] getArray1() { return array1.clone(); } //----------------------------------------------------------------------- /** * Gets the array2. * @return the value of the property, not null */ public String[] getArray2() { return array2.clone(); } //----------------------------------------------------------------------- /** * Gets the array3. * @return the value of the property, not null */ public String[] getArray3() { return (String[]) array3.clone(); } //----------------------------------------------------------------------- /** * Gets the dateNullable. * @return the value of the property */ public Date getDateNullable() { return (dateNullable != null ? (Date) dateNullable.clone() : null); } //----------------------------------------------------------------------- /** * Gets the array1Nullable. * @return the value of the property */ public String[] getArray1Nullable() { return (array1Nullable != null ? array1Nullable.clone() : null); } //----------------------------------------------------------------------- /** * Gets the array2Nullable. * @return the value of the property */ public String[] getArray2Nullable() { return (array2Nullable != null ? (String[]) array2Nullable.clone() : null); } //----------------------------------------------------------------------- /** * Gets the array3Nullable. * @return the value of the property */ public String[] getArray3Nullable() { return (array3Nullable != null ? array3Nullable.clone() : null); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmClone other = (ImmClone) obj; return JodaBeanUtils.equal(this.date, other.date) && JodaBeanUtils.equal(this.array1, other.array1) && JodaBeanUtils.equal(this.array2, other.array2) && JodaBeanUtils.equal(this.array3, other.array3) && JodaBeanUtils.equal(this.dateNullable, other.dateNullable) && JodaBeanUtils.equal(this.array1Nullable, other.array1Nullable) && JodaBeanUtils.equal(this.array2Nullable, other.array2Nullable) && JodaBeanUtils.equal(this.array3Nullable, other.array3Nullable); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(date); hash = hash * 31 + JodaBeanUtils.hashCode(array1); hash = hash * 31 + JodaBeanUtils.hashCode(array2); hash = hash * 31 + JodaBeanUtils.hashCode(array3); hash = hash * 31 + JodaBeanUtils.hashCode(dateNullable); hash = hash * 31 + JodaBeanUtils.hashCode(array1Nullable); hash = hash * 31 + JodaBeanUtils.hashCode(array2Nullable); hash = hash * 31 + JodaBeanUtils.hashCode(array3Nullable); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("ImmClone{"); buf.append("date").append('=').append(JodaBeanUtils.toString(date)).append(',').append(' '); buf.append("array1").append('=').append(JodaBeanUtils.toString(array1)).append(',').append(' '); buf.append("array2").append('=').append(JodaBeanUtils.toString(array2)).append(',').append(' '); buf.append("array3").append('=').append(JodaBeanUtils.toString(array3)).append(',').append(' '); buf.append("dateNullable").append('=').append(JodaBeanUtils.toString(dateNullable)).append(',').append(' '); buf.append("array1Nullable").append('=').append(JodaBeanUtils.toString(array1Nullable)).append(',').append(' '); buf.append("array2Nullable").append('=').append(JodaBeanUtils.toString(array2Nullable)).append(',').append(' '); buf.append("array3Nullable").append('=').append(JodaBeanUtils.toString(array3Nullable)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmClone}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code date} property. */ private final MetaProperty date = DirectMetaProperty.ofImmutable( this, "date", ImmClone.class, Date.class); /** * The meta-property for the {@code array1} property. */ private final MetaProperty array1 = DirectMetaProperty.ofImmutable( this, "array1", ImmClone.class, String[].class); /** * The meta-property for the {@code array2} property. */ private final MetaProperty array2 = DirectMetaProperty.ofImmutable( this, "array2", ImmClone.class, String[].class); /** * The meta-property for the {@code array3} property. */ private final MetaProperty array3 = DirectMetaProperty.ofImmutable( this, "array3", ImmClone.class, String[].class); /** * The meta-property for the {@code dateNullable} property. */ private final MetaProperty dateNullable = DirectMetaProperty.ofImmutable( this, "dateNullable", ImmClone.class, Date.class); /** * The meta-property for the {@code array1Nullable} property. */ private final MetaProperty array1Nullable = DirectMetaProperty.ofImmutable( this, "array1Nullable", ImmClone.class, String[].class); /** * The meta-property for the {@code array2Nullable} property. */ private final MetaProperty array2Nullable = DirectMetaProperty.ofImmutable( this, "array2Nullable", ImmClone.class, String[].class); /** * The meta-property for the {@code array3Nullable} property. */ private final MetaProperty array3Nullable = DirectMetaProperty.ofImmutable( this, "array3Nullable", ImmClone.class, String[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "date", "array1", "array2", "array3", "dateNullable", "array1Nullable", "array2Nullable", "array3Nullable"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3076014: // date return this.date; case -1409165064: // array1 return this.array1; case -1409165063: // array2 return this.array2; case -1409165062: // array3 return this.array3; case 781387055: // dateNullable return this.dateNullable; case 221578361: // array1Nullable return this.array1Nullable; case -1585876102: // array2Nullable return this.array2Nullable; case 901636731: // array3Nullable return this.array3Nullable; } return super.metaPropertyGet(propertyName); } @Override public ImmClone.Builder builder() { return new ImmClone.Builder(); } @Override public Class beanType() { return ImmClone.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code date} property. * @return the meta-property, not null */ public MetaProperty date() { return date; } /** * The meta-property for the {@code array1} property. * @return the meta-property, not null */ public MetaProperty array1() { return array1; } /** * The meta-property for the {@code array2} property. * @return the meta-property, not null */ public MetaProperty array2() { return array2; } /** * The meta-property for the {@code array3} property. * @return the meta-property, not null */ public MetaProperty array3() { return array3; } /** * The meta-property for the {@code dateNullable} property. * @return the meta-property, not null */ public MetaProperty dateNullable() { return dateNullable; } /** * The meta-property for the {@code array1Nullable} property. * @return the meta-property, not null */ public MetaProperty array1Nullable() { return array1Nullable; } /** * The meta-property for the {@code array2Nullable} property. * @return the meta-property, not null */ public MetaProperty array2Nullable() { return array2Nullable; } /** * The meta-property for the {@code array3Nullable} property. * @return the meta-property, not null */ public MetaProperty array3Nullable() { return array3Nullable; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3076014: // date return ((ImmClone) bean).getDate(); case -1409165064: // array1 return ((ImmClone) bean).getArray1(); case -1409165063: // array2 return ((ImmClone) bean).getArray2(); case -1409165062: // array3 return ((ImmClone) bean).getArray3(); case 781387055: // dateNullable return ((ImmClone) bean).getDateNullable(); case 221578361: // array1Nullable return ((ImmClone) bean).getArray1Nullable(); case -1585876102: // array2Nullable return ((ImmClone) bean).getArray2Nullable(); case 901636731: // array3Nullable return ((ImmClone) bean).getArray3Nullable(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmClone}. */ public static final class Builder extends DirectFieldsBeanBuilder { private Date date; private String[] array1; private String[] array2; private String[] array3; private Date dateNullable; private String[] array1Nullable; private String[] array2Nullable; private String[] array3Nullable; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmClone beanToCopy) { this.date = (Date) beanToCopy.getDate().clone(); this.array1 = beanToCopy.getArray1().clone(); this.array2 = beanToCopy.getArray2().clone(); this.array3 = beanToCopy.getArray3().clone(); this.dateNullable = (beanToCopy.getDateNullable() != null ? (Date) beanToCopy.getDateNullable().clone() : null); this.array1Nullable = (beanToCopy.getArray1Nullable() != null ? beanToCopy.getArray1Nullable().clone() : null); this.array2Nullable = (beanToCopy.getArray2Nullable() != null ? beanToCopy.getArray2Nullable().clone() : null); this.array3Nullable = (beanToCopy.getArray3Nullable() != null ? beanToCopy.getArray3Nullable().clone() : null); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3076014: // date return this.date; case -1409165064: // array1 return this.array1; case -1409165063: // array2 return this.array2; case -1409165062: // array3 return this.array3; case 781387055: // dateNullable return this.dateNullable; case 221578361: // array1Nullable return this.array1Nullable; case -1585876102: // array2Nullable return this.array2Nullable; case 901636731: // array3Nullable return this.array3Nullable; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3076014: // date this.date = (Date) newValue; break; case -1409165064: // array1 this.array1 = (String[]) newValue; break; case -1409165063: // array2 this.array2 = (String[]) newValue; break; case -1409165062: // array3 this.array3 = (String[]) newValue; break; case 781387055: // dateNullable this.dateNullable = (Date) newValue; break; case 221578361: // array1Nullable this.array1Nullable = (String[]) newValue; break; case -1585876102: // array2Nullable this.array2Nullable = (String[]) newValue; break; case 901636731: // array3Nullable this.array3Nullable = (String[]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmClone build() { return new ImmClone( date, array1, array2, array3, dateNullable, array1Nullable, array2Nullable, array3Nullable); } //----------------------------------------------------------------------- /** * Sets the date. * @param date the new value, not null * @return this, for chaining, not null */ public Builder date(Date date) { JodaBeanUtils.notNull(date, "date"); this.date = date; return this; } /** * Sets the array1. * @param array1 the new value, not null * @return this, for chaining, not null */ public Builder array1(String... array1) { JodaBeanUtils.notNull(array1, "array1"); this.array1 = array1; return this; } /** * Sets the array2. * @param array2 the new value, not null * @return this, for chaining, not null */ public Builder array2(String... array2) { JodaBeanUtils.notNull(array2, "array2"); this.array2 = array2; return this; } /** * Sets the array3. * @param array3 the new value, not null * @return this, for chaining, not null */ public Builder array3(String... array3) { JodaBeanUtils.notNull(array3, "array3"); this.array3 = array3; return this; } /** * Sets the dateNullable. * @param dateNullable the new value * @return this, for chaining, not null */ public Builder dateNullable(Date dateNullable) { this.dateNullable = dateNullable; return this; } /** * Sets the array1Nullable. * @param array1Nullable the new value * @return this, for chaining, not null */ public Builder array1Nullable(String... array1Nullable) { this.array1Nullable = array1Nullable; return this; } /** * Sets the array2Nullable. * @param array2Nullable the new value * @return this, for chaining, not null */ public Builder array2Nullable(String... array2Nullable) { this.array2Nullable = array2Nullable; return this; } /** * Sets the array3Nullable. * @param array3Nullable the new value * @return this, for chaining, not null */ public Builder array3Nullable(String... array3Nullable) { this.array3Nullable = array3Nullable; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("ImmClone.Builder{"); buf.append("date").append('=').append(JodaBeanUtils.toString(date)).append(',').append(' '); buf.append("array1").append('=').append(JodaBeanUtils.toString(array1)).append(',').append(' '); buf.append("array2").append('=').append(JodaBeanUtils.toString(array2)).append(',').append(' '); buf.append("array3").append('=').append(JodaBeanUtils.toString(array3)).append(',').append(' '); buf.append("dateNullable").append('=').append(JodaBeanUtils.toString(dateNullable)).append(',').append(' '); buf.append("array1Nullable").append('=').append(JodaBeanUtils.toString(array1Nullable)).append(',').append(' '); buf.append("array2Nullable").append('=').append(JodaBeanUtils.toString(array2Nullable)).append(',').append(' '); buf.append("array3Nullable").append('=').append(JodaBeanUtils.toString(array3Nullable)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmComplexAnnotation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock bean for complex annotation testing. */ @BeanDefinition(cacheHashCode = true, factoryName = "create") @ClassAnnotation(ImmComplexAnnotation.class) @ComplexAnnotation({ @SimpleAnnotation(first = "1", second = "2", third = "3"), @SimpleAnnotation(first = "1", second = "2", third = "3") }) public final class ImmComplexAnnotation implements ImmutableBean, Cloneable, Serializable { @PropertyDefinition private final double value; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmComplexAnnotation}. * @return the meta-bean, not null */ public static ImmComplexAnnotation.Meta meta() { return ImmComplexAnnotation.Meta.INSTANCE; } static { MetaBean.register(ImmComplexAnnotation.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * The cached hash code, using the racy single-check idiom. */ private transient int cacheHashCode; /** * Obtains an instance. * @param value the value of the property * @return the instance */ public static ImmComplexAnnotation create( double value) { return new ImmComplexAnnotation( value); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmComplexAnnotation.Builder builder() { return new ImmComplexAnnotation.Builder(); } private ImmComplexAnnotation( double value) { this.value = value; } @Override public ImmComplexAnnotation.Meta metaBean() { return ImmComplexAnnotation.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property */ public double getValue() { return value; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmComplexAnnotation other = (ImmComplexAnnotation) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = cacheHashCode; if (hash == 0) { hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); cacheHashCode = hash; } return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmComplexAnnotation{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmComplexAnnotation}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofImmutable( this, "value", ImmComplexAnnotation.class, Double.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmComplexAnnotation.Builder builder() { return new ImmComplexAnnotation.Builder(); } @Override public Class beanType() { return ImmComplexAnnotation.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmComplexAnnotation) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmComplexAnnotation}. */ public static final class Builder extends DirectFieldsBeanBuilder { private double value; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmComplexAnnotation beanToCopy) { this.value = beanToCopy.getValue(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (Double) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmComplexAnnotation build() { return new ImmComplexAnnotation( value); } //----------------------------------------------------------------------- /** * Sets the value. * @param value the new value * @return this, for chaining, not null */ public Builder value(double value) { this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmComplexAnnotation.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmDefault.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.ImmutableDefaults; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Wraps a defaulted value, used for testing. */ @BeanDefinition(factoryName = "of") public final class ImmDefault implements ImmutableBean { /** * The value. */ @PropertyDefinition(validate = "notNull") private final String value; @ImmutableDefaults private static void applyDefaults(Builder builder) { builder.value = "Defaulted"; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmDefault}. * @return the meta-bean, not null */ public static ImmDefault.Meta meta() { return ImmDefault.Meta.INSTANCE; } static { MetaBean.register(ImmDefault.Meta.INSTANCE); } /** * Obtains an instance. * @param value the value of the property, not null * @return the instance */ public static ImmDefault of( String value) { return new ImmDefault( value); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmDefault.Builder builder() { return new ImmDefault.Builder(); } private ImmDefault( String value) { JodaBeanUtils.notNull(value, "value"); this.value = value; } @Override public ImmDefault.Meta metaBean() { return ImmDefault.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property, not null */ public String getValue() { return value; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmDefault other = (ImmDefault) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmDefault{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmDefault}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofImmutable( this, "value", ImmDefault.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmDefault.Builder builder() { return new ImmDefault.Builder(); } @Override public Class beanType() { return ImmDefault.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmDefault) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmDefault}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String value; /** * Restricted constructor. */ private Builder() { applyDefaults(this); } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmDefault beanToCopy) { this.value = beanToCopy.getValue(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmDefault build() { return new ImmDefault( value); } //----------------------------------------------------------------------- /** * Sets the value. * @param value the new value, not null * @return this, for chaining, not null */ public Builder value(String value) { JodaBeanUtils.notNull(value, "value"); this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmDefault.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmDeprecated.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class ImmDeprecated implements Cloneable, ImmutableBean { /** * The field with deprecated annotation and Javadoc tag. * @deprecated Use something else */ @Deprecated @PropertyDefinition private final String deprecatedBoth; /** * The field with deprecated Javadoc tag only. * @deprecated Use something else */ @PropertyDefinition private final String deprecatedJavadoc; @Deprecated @PropertyDefinition private final String deprecatedAnnotation; @Deprecated @PropertyDefinition(get = "optional") private final String deprecatedOptional; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmDeprecated}. * @return the meta-bean, not null */ public static ImmDeprecated.Meta meta() { return ImmDeprecated.Meta.INSTANCE; } static { MetaBean.register(ImmDeprecated.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmDeprecated.Builder builder() { return new ImmDeprecated.Builder(); } private ImmDeprecated( String deprecatedBoth, String deprecatedJavadoc, String deprecatedAnnotation, String deprecatedOptional) { this.deprecatedBoth = deprecatedBoth; this.deprecatedJavadoc = deprecatedJavadoc; this.deprecatedAnnotation = deprecatedAnnotation; this.deprecatedOptional = deprecatedOptional; } @Override public ImmDeprecated.Meta metaBean() { return ImmDeprecated.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the field with deprecated annotation and Javadoc tag. * @return the value of the property * @deprecated Use something else */ @Deprecated public String getDeprecatedBoth() { return deprecatedBoth; } //----------------------------------------------------------------------- /** * Gets the field with deprecated Javadoc tag only. * @return the value of the property * @deprecated Use something else */ @Deprecated public String getDeprecatedJavadoc() { return deprecatedJavadoc; } //----------------------------------------------------------------------- /** * Gets the deprecatedAnnotation. * @return the value of the property * @deprecated Deprecated */ @Deprecated public String getDeprecatedAnnotation() { return deprecatedAnnotation; } //----------------------------------------------------------------------- /** * Gets the deprecatedOptional. * @return the optional value of the property, not null * @deprecated Deprecated */ @Deprecated public Optional getDeprecatedOptional() { return Optional.ofNullable(deprecatedOptional); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmDeprecated other = (ImmDeprecated) obj; return JodaBeanUtils.equal(this.deprecatedBoth, other.deprecatedBoth) && JodaBeanUtils.equal(this.deprecatedJavadoc, other.deprecatedJavadoc) && JodaBeanUtils.equal(this.deprecatedAnnotation, other.deprecatedAnnotation) && JodaBeanUtils.equal(this.deprecatedOptional, other.deprecatedOptional); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(deprecatedBoth); hash = hash * 31 + JodaBeanUtils.hashCode(deprecatedJavadoc); hash = hash * 31 + JodaBeanUtils.hashCode(deprecatedAnnotation); hash = hash * 31 + JodaBeanUtils.hashCode(deprecatedOptional); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmDeprecated{"); buf.append("deprecatedBoth").append('=').append(JodaBeanUtils.toString(deprecatedBoth)).append(',').append(' '); buf.append("deprecatedJavadoc").append('=').append(JodaBeanUtils.toString(deprecatedJavadoc)).append(',').append(' '); buf.append("deprecatedAnnotation").append('=').append(JodaBeanUtils.toString(deprecatedAnnotation)).append(',').append(' '); buf.append("deprecatedOptional").append('=').append(JodaBeanUtils.toString(deprecatedOptional)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmDeprecated}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code deprecatedBoth} property. */ private final MetaProperty deprecatedBoth = DirectMetaProperty.ofImmutable( this, "deprecatedBoth", ImmDeprecated.class, String.class); /** * The meta-property for the {@code deprecatedJavadoc} property. */ private final MetaProperty deprecatedJavadoc = DirectMetaProperty.ofImmutable( this, "deprecatedJavadoc", ImmDeprecated.class, String.class); /** * The meta-property for the {@code deprecatedAnnotation} property. */ private final MetaProperty deprecatedAnnotation = DirectMetaProperty.ofImmutable( this, "deprecatedAnnotation", ImmDeprecated.class, String.class); /** * The meta-property for the {@code deprecatedOptional} property. */ private final MetaProperty deprecatedOptional = DirectMetaProperty.ofImmutable( this, "deprecatedOptional", ImmDeprecated.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "deprecatedBoth", "deprecatedJavadoc", "deprecatedAnnotation", "deprecatedOptional"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth return this.deprecatedBoth; case -1632501085: // deprecatedJavadoc return this.deprecatedJavadoc; case 1044703554: // deprecatedAnnotation return this.deprecatedAnnotation; case 1434300979: // deprecatedOptional return this.deprecatedOptional; } return super.metaPropertyGet(propertyName); } @Override public ImmDeprecated.Builder builder() { return new ImmDeprecated.Builder(); } @Override public Class beanType() { return ImmDeprecated.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code deprecatedBoth} property. * @return the meta-property, not null * @deprecated Use something else */ @Deprecated public MetaProperty deprecatedBoth() { return deprecatedBoth; } /** * The meta-property for the {@code deprecatedJavadoc} property. * @return the meta-property, not null * @deprecated Use something else */ @Deprecated public MetaProperty deprecatedJavadoc() { return deprecatedJavadoc; } /** * The meta-property for the {@code deprecatedAnnotation} property. * @return the meta-property, not null * @deprecated Deprecated */ @Deprecated public MetaProperty deprecatedAnnotation() { return deprecatedAnnotation; } /** * The meta-property for the {@code deprecatedOptional} property. * @return the meta-property, not null * @deprecated Deprecated */ @Deprecated public MetaProperty deprecatedOptional() { return deprecatedOptional; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth return ((ImmDeprecated) bean).getDeprecatedBoth(); case -1632501085: // deprecatedJavadoc return ((ImmDeprecated) bean).getDeprecatedJavadoc(); case 1044703554: // deprecatedAnnotation return ((ImmDeprecated) bean).getDeprecatedAnnotation(); case 1434300979: // deprecatedOptional return ((ImmDeprecated) bean).deprecatedOptional; } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmDeprecated}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String deprecatedBoth; private String deprecatedJavadoc; private String deprecatedAnnotation; private String deprecatedOptional; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmDeprecated beanToCopy) { this.deprecatedBoth = beanToCopy.getDeprecatedBoth(); this.deprecatedJavadoc = beanToCopy.getDeprecatedJavadoc(); this.deprecatedAnnotation = beanToCopy.getDeprecatedAnnotation(); this.deprecatedOptional = beanToCopy.deprecatedOptional; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth return this.deprecatedBoth; case -1632501085: // deprecatedJavadoc return this.deprecatedJavadoc; case 1044703554: // deprecatedAnnotation return this.deprecatedAnnotation; case 1434300979: // deprecatedOptional return this.deprecatedOptional; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth this.deprecatedBoth = (String) newValue; break; case -1632501085: // deprecatedJavadoc this.deprecatedJavadoc = (String) newValue; break; case 1044703554: // deprecatedAnnotation this.deprecatedAnnotation = (String) newValue; break; case 1434300979: // deprecatedOptional this.deprecatedOptional = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmDeprecated build() { return new ImmDeprecated( deprecatedBoth, deprecatedJavadoc, deprecatedAnnotation, deprecatedOptional); } //----------------------------------------------------------------------- /** * Sets the field with deprecated annotation and Javadoc tag. * @param deprecatedBoth the new value * @return this, for chaining, not null * @deprecated Use something else */ @Deprecated public Builder deprecatedBoth(String deprecatedBoth) { this.deprecatedBoth = deprecatedBoth; return this; } /** * Sets the field with deprecated Javadoc tag only. * @param deprecatedJavadoc the new value * @return this, for chaining, not null * @deprecated Use something else */ @Deprecated public Builder deprecatedJavadoc(String deprecatedJavadoc) { this.deprecatedJavadoc = deprecatedJavadoc; return this; } /** * Sets the deprecatedAnnotation. * @param deprecatedAnnotation the new value * @return this, for chaining, not null * @deprecated Deprecated */ @Deprecated public Builder deprecatedAnnotation(String deprecatedAnnotation) { this.deprecatedAnnotation = deprecatedAnnotation; return this; } /** * Sets the deprecatedOptional. * @param deprecatedOptional the new value * @return this, for chaining, not null * @deprecated Deprecated */ @Deprecated public Builder deprecatedOptional(String deprecatedOptional) { this.deprecatedOptional = deprecatedOptional; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmDeprecated.Builder{"); buf.append("deprecatedBoth").append('=').append(JodaBeanUtils.toString(deprecatedBoth)).append(',').append(' '); buf.append("deprecatedJavadoc").append('=').append(JodaBeanUtils.toString(deprecatedJavadoc)).append(',').append(' '); buf.append("deprecatedAnnotation").append('=').append(JodaBeanUtils.toString(deprecatedAnnotation)).append(',').append(' '); buf.append("deprecatedOptional").append('=').append(JodaBeanUtils.toString(deprecatedOptional)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmDocumentationHolder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.ImmutableConstructor; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * This tests a generic ? property with a manual argument constructor. * * @author Stephen Colebourne */ @BeanDefinition public final class ImmDocumentationHolder implements ImmutableBean, Serializable { /** Serialization. */ private static final long serialVersionUID = 1L; /** The documentation. */ @PropertyDefinition private final Documentation documentation; @ImmutableConstructor private ImmDocumentationHolder( Documentation documentation) { this.documentation = documentation; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmDocumentationHolder}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmDocumentationHolder.Meta meta() { return ImmDocumentationHolder.Meta.INSTANCE; } /** * The meta-bean for {@code ImmDocumentationHolder}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmDocumentationHolder.Meta metaImmDocumentationHolder(Class cls) { return ImmDocumentationHolder.Meta.INSTANCE; } static { MetaBean.register(ImmDocumentationHolder.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static ImmDocumentationHolder.Builder builder() { return new ImmDocumentationHolder.Builder<>(); } @SuppressWarnings("unchecked") @Override public ImmDocumentationHolder.Meta metaBean() { return ImmDocumentationHolder.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the documentation. * @return the value of the property */ public Documentation getDocumentation() { return documentation; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmDocumentationHolder other = (ImmDocumentationHolder) obj; return JodaBeanUtils.equal(this.documentation, other.documentation); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(documentation); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmDocumentationHolder{"); buf.append("documentation").append('=').append(JodaBeanUtils.toString(documentation)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmDocumentationHolder}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code documentation} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> documentation = DirectMetaProperty.ofImmutable( this, "documentation", ImmDocumentationHolder.class, (Class) Documentation.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "documentation"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1587405498: // documentation return this.documentation; } return super.metaPropertyGet(propertyName); } @Override public ImmDocumentationHolder.Builder builder() { return new ImmDocumentationHolder.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmDocumentationHolder.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code documentation} property. * @return the meta-property, not null */ public MetaProperty> documentation() { return documentation; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1587405498: // documentation return ((ImmDocumentationHolder) bean).getDocumentation(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmDocumentationHolder}. * @param the type */ public static final class Builder extends DirectFieldsBeanBuilder> { private Documentation documentation; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmDocumentationHolder beanToCopy) { this.documentation = beanToCopy.getDocumentation(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 1587405498: // documentation return this.documentation; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 1587405498: // documentation this.documentation = (Documentation) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmDocumentationHolder build() { return new ImmDocumentationHolder<>( documentation); } //----------------------------------------------------------------------- /** * Sets the documentation. * @param documentation the new value * @return this, for chaining, not null */ public Builder documentation(Documentation documentation) { this.documentation = documentation; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmDocumentationHolder.Builder{"); buf.append("documentation").append('=').append(JodaBeanUtils.toString(documentation)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmDocumentationResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.ImmutableConstructor; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * This tests a generic ? property with a manual builder constructor. * * @author Stephen Colebourne */ @BeanDefinition public final class ImmDocumentationResult implements ImmutableBean { /** The documentation. */ @PropertyDefinition(alias = "underlying") private final Documentation documentation; @ImmutableConstructor private ImmDocumentationResult(Builder builder) { this.documentation = builder.documentation; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmDocumentationResult}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmDocumentationResult.Meta meta() { return ImmDocumentationResult.Meta.INSTANCE; } /** * The meta-bean for {@code ImmDocumentationResult}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmDocumentationResult.Meta metaImmDocumentationResult(Class cls) { return ImmDocumentationResult.Meta.INSTANCE; } static { MetaBean.register(ImmDocumentationResult.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static ImmDocumentationResult.Builder builder() { return new ImmDocumentationResult.Builder<>(); } @SuppressWarnings("unchecked") @Override public ImmDocumentationResult.Meta metaBean() { return ImmDocumentationResult.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the documentation. * @return the value of the property */ public Documentation getDocumentation() { return documentation; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmDocumentationResult other = (ImmDocumentationResult) obj; return JodaBeanUtils.equal(this.documentation, other.documentation); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(documentation); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmDocumentationResult{"); buf.append("documentation").append('=').append(JodaBeanUtils.toString(documentation)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmDocumentationResult}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code documentation} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> documentation = DirectMetaProperty.ofImmutable( this, "documentation", ImmDocumentationResult.class, (Class) Documentation.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "documentation"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1587405498: // documentation case -1770633379: // underlying (alias) return this.documentation; } return super.metaPropertyGet(propertyName); } @Override public ImmDocumentationResult.Builder builder() { return new ImmDocumentationResult.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmDocumentationResult.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code documentation} property. * @return the meta-property, not null */ public MetaProperty> documentation() { return documentation; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1587405498: // documentation case -1770633379: // underlying (alias) return ((ImmDocumentationResult) bean).getDocumentation(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmDocumentationResult}. * @param the type */ public static final class Builder extends DirectFieldsBeanBuilder> { private Documentation documentation; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmDocumentationResult beanToCopy) { this.documentation = beanToCopy.getDocumentation(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 1587405498: // documentation case -1770633379: // underlying (alias) return this.documentation; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 1587405498: // documentation case -1770633379: // underlying (alias) this.documentation = (Documentation) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmDocumentationResult build() { return new ImmDocumentationResult<>(this); } //----------------------------------------------------------------------- /** * Sets the documentation. * @param documentation the new value * @return this, for chaining, not null */ public Builder documentation(Documentation documentation) { this.documentation = documentation; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmDocumentationResult.Builder{"); buf.append("documentation").append('=').append(JodaBeanUtils.toString(documentation)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmDoubleArray.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.impl.direct.DirectPrivateBeanBuilder; /** * Mock JavaBean, used for testing. */ @BeanDefinition(builderScope = "private", factoryName = "of") public final class ImmDoubleArray implements Serializable, ImmutableBean { /** The double values. */ @PropertyDefinition(validate = "notNull") private final double[] values; /** The second lot of values. */ @PropertyDefinition(validate = "notNull") private final double[] values2; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmDoubleArray}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmDoubleArray.Meta meta() { return ImmDoubleArray.Meta.INSTANCE; } /** * The meta-bean for {@code ImmDoubleArray}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmDoubleArray.Meta metaImmDoubleArray(Class cls) { return ImmDoubleArray.Meta.INSTANCE; } static { MetaBean.register(ImmDoubleArray.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Obtains an instance. * @param the type * @param values the value of the property, not null * @param values2 the value of the property, not null * @return the instance */ public static ImmDoubleArray of( double[] values, double[] values2) { return new ImmDoubleArray<>( values, values2); } private ImmDoubleArray( double[] values, double[] values2) { JodaBeanUtils.notNull(values, "values"); JodaBeanUtils.notNull(values2, "values2"); this.values = values.clone(); this.values2 = values2.clone(); } @SuppressWarnings("unchecked") @Override public ImmDoubleArray.Meta metaBean() { return ImmDoubleArray.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the double values. * @return the value of the property, not null */ public double[] getValues() { return values.clone(); } //----------------------------------------------------------------------- /** * Gets the second lot of values. * @return the value of the property, not null */ public double[] getValues2() { return values2.clone(); } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmDoubleArray other = (ImmDoubleArray) obj; return JodaBeanUtils.equal(this.values, other.values) && JodaBeanUtils.equal(this.values2, other.values2); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(values); hash = hash * 31 + JodaBeanUtils.hashCode(values2); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmDoubleArray{"); buf.append("values").append('=').append(JodaBeanUtils.toString(values)).append(',').append(' '); buf.append("values2").append('=').append(JodaBeanUtils.toString(values2)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmDoubleArray}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code values} property. */ private final MetaProperty values = DirectMetaProperty.ofImmutable( this, "values", ImmDoubleArray.class, double[].class); /** * The meta-property for the {@code values2} property. */ private final MetaProperty values2 = DirectMetaProperty.ofImmutable( this, "values2", ImmDoubleArray.class, double[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "values", "values2"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -823812830: // values return this.values; case 231606096: // values2 return this.values2; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new ImmDoubleArray.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmDoubleArray.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code values} property. * @return the meta-property, not null */ public MetaProperty values() { return values; } /** * The meta-property for the {@code values2} property. * @return the meta-property, not null */ public MetaProperty values2() { return values2; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -823812830: // values return ((ImmDoubleArray) bean).getValues(); case 231606096: // values2 return ((ImmDoubleArray) bean).getValues2(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmDoubleArray}. * @param the type */ private static final class Builder extends DirectPrivateBeanBuilder> { private double[] values; private double[] values2; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -823812830: // values return this.values; case 231606096: // values2 return this.values2; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -823812830: // values this.values = (double[]) newValue; break; case 231606096: // values2 this.values2 = (double[]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public ImmDoubleArray build() { return new ImmDoubleArray<>( values, values2); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmDoubleArray.Builder{"); buf.append("values").append('=').append(JodaBeanUtils.toString(values)).append(',').append(' '); buf.append("values2").append('=').append(JodaBeanUtils.toString(values2)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmDoubleFloat.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock immutable bean, used for testing deserialization. */ @BeanDefinition public final class ImmDoubleFloat implements ImmutableBean { @PropertyDefinition private final double a; @PropertyDefinition private final double b; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmDoubleFloat}. * @return the meta-bean, not null */ public static ImmDoubleFloat.Meta meta() { return ImmDoubleFloat.Meta.INSTANCE; } static { MetaBean.register(ImmDoubleFloat.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmDoubleFloat.Builder builder() { return new ImmDoubleFloat.Builder(); } private ImmDoubleFloat( double a, double b) { this.a = a; this.b = b; } @Override public ImmDoubleFloat.Meta metaBean() { return ImmDoubleFloat.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the a. * @return the value of the property */ public double getA() { return a; } //----------------------------------------------------------------------- /** * Gets the b. * @return the value of the property */ public double getB() { return b; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmDoubleFloat other = (ImmDoubleFloat) obj; return JodaBeanUtils.equal(this.a, other.a) && JodaBeanUtils.equal(this.b, other.b); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(a); hash = hash * 31 + JodaBeanUtils.hashCode(b); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmDoubleFloat{"); buf.append("a").append('=').append(JodaBeanUtils.toString(a)).append(',').append(' '); buf.append("b").append('=').append(JodaBeanUtils.toString(b)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmDoubleFloat}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code a} property. */ private final MetaProperty a = DirectMetaProperty.ofImmutable( this, "a", ImmDoubleFloat.class, Double.TYPE); /** * The meta-property for the {@code b} property. */ private final MetaProperty b = DirectMetaProperty.ofImmutable( this, "b", ImmDoubleFloat.class, Double.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "a", "b"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97: // a return this.a; case 98: // b return this.b; } return super.metaPropertyGet(propertyName); } @Override public ImmDoubleFloat.Builder builder() { return new ImmDoubleFloat.Builder(); } @Override public Class beanType() { return ImmDoubleFloat.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code a} property. * @return the meta-property, not null */ public MetaProperty a() { return a; } /** * The meta-property for the {@code b} property. * @return the meta-property, not null */ public MetaProperty b() { return b; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97: // a return ((ImmDoubleFloat) bean).getA(); case 98: // b return ((ImmDoubleFloat) bean).getB(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmDoubleFloat}. */ public static final class Builder extends DirectFieldsBeanBuilder { private double a; private double b; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmDoubleFloat beanToCopy) { this.a = beanToCopy.getA(); this.b = beanToCopy.getB(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 97: // a return this.a; case 98: // b return this.b; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 97: // a this.a = (Double) newValue; break; case 98: // b this.b = (Double) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmDoubleFloat build() { return new ImmDoubleFloat( a, b); } //----------------------------------------------------------------------- /** * Sets the a. * @param a the new value * @return this, for chaining, not null */ public Builder a(double a) { this.a = a; return this; } /** * Sets the b. * @param b the new value * @return this, for chaining, not null */ public Builder b(double b) { this.b = b; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmDoubleFloat.Builder{"); buf.append("a").append('=').append(JodaBeanUtils.toString(a)).append(',').append(' '); buf.append("b").append('=').append(JodaBeanUtils.toString(b)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmEmpty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.beans.ConstructorProperties; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock immutable empty bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "public@ConstructorProperties") public final class ImmEmpty implements ImmutableBean { // NOTE: open braces on a new line //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmEmpty}. * @return the meta-bean, not null */ public static ImmEmpty.Meta meta() { return ImmEmpty.Meta.INSTANCE; } static { MetaBean.register(ImmEmpty.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmEmpty.Builder builder() { return new ImmEmpty.Builder(); } /** * Creates an instance. */ @ConstructorProperties({}) public ImmEmpty() { } @Override public ImmEmpty.Meta metaBean() { return ImmEmpty.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return true; } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("ImmEmpty{"); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmEmpty}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null); /** * Restricted constructor. */ private Meta() { } @Override public ImmEmpty.Builder builder() { return new ImmEmpty.Builder(); } @Override public Class beanType() { return ImmEmpty.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmEmpty}. */ public static final class Builder extends DirectFieldsBeanBuilder { /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { throw new NoSuchElementException("Unknown property: " + propertyName); } @Override public Builder set(String propertyName, Object newValue) { throw new NoSuchElementException("Unknown property: " + propertyName); } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmEmpty build() { return new ImmEmpty(); } //----------------------------------------------------------------------- @Override public String toString() { return "ImmEmpty.Builder{}"; } } //-------------------------- AUTOGENERATED END -------------------------- // an inner class with equals/hashCode/toString static class InnerClass { private final String value; public InnerClass(String value) { this.value = value; } @Override public int hashCode() { return Objects.hashCode(value); } @Override public boolean equals(Object obj) { return obj instanceof InnerClass other && Objects.equals(value, other.value); } @Override public String toString() { return value; } } } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmFieldGetter.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class ImmFieldGetter implements ImmutableBean { @PropertyDefinition(get = "field") private final String value; public String getValue() { if (value == null) { throw new NullPointerException(); } return value; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmFieldGetter}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmFieldGetter.Meta meta() { return ImmFieldGetter.Meta.INSTANCE; } /** * The meta-bean for {@code ImmFieldGetter}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmFieldGetter.Meta metaImmFieldGetter(Class cls) { return ImmFieldGetter.Meta.INSTANCE; } static { MetaBean.register(ImmFieldGetter.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static ImmFieldGetter.Builder builder() { return new ImmFieldGetter.Builder<>(); } private ImmFieldGetter( String value) { this.value = value; } @SuppressWarnings("unchecked") @Override public ImmFieldGetter.Meta metaBean() { return ImmFieldGetter.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmFieldGetter other = (ImmFieldGetter) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmFieldGetter{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmFieldGetter}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofImmutable( this, "value", ImmFieldGetter.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmFieldGetter.Builder builder() { return new ImmFieldGetter.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmFieldGetter.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmFieldGetter) bean).value; } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmFieldGetter}. * @param the type */ public static final class Builder extends DirectFieldsBeanBuilder> { private String value; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmFieldGetter beanToCopy) { this.value = beanToCopy.value; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmFieldGetter build() { return new ImmFieldGetter<>( value); } //----------------------------------------------------------------------- /** * Sets the value. * @param value the new value * @return this, for chaining, not null */ public Builder value(String value) { this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmFieldGetter.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public", factoryName = "of") public final class ImmGeneric implements ImmutableBean { /** The name. */ @PropertyDefinition(validate = "notNull") private final T value; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmGeneric}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmGeneric.Meta meta() { return ImmGeneric.Meta.INSTANCE; } /** * The meta-bean for {@code ImmGeneric}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmGeneric.Meta metaImmGeneric(Class cls) { return ImmGeneric.Meta.INSTANCE; } static { MetaBean.register(ImmGeneric.Meta.INSTANCE); } /** * Obtains an instance. * @param the type * @param value the value of the property, not null * @return the instance */ public static ImmGeneric of( T value) { return new ImmGeneric<>( value); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static ImmGeneric.Builder builder() { return new ImmGeneric.Builder<>(); } private ImmGeneric( T value) { JodaBeanUtils.notNull(value, "value"); this.value = value; } @SuppressWarnings("unchecked") @Override public ImmGeneric.Meta metaBean() { return ImmGeneric.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public T getValue() { return value; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmGeneric other = (ImmGeneric) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGeneric{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmGeneric}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty value = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "value", ImmGeneric.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmGeneric.Builder builder() { return new ImmGeneric.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmGeneric.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmGeneric) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmGeneric}. * @param the type */ public static final class Builder extends DirectFieldsBeanBuilder> { private T value; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmGeneric beanToCopy) { this.value = beanToCopy.getValue(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (T) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmGeneric build() { return new ImmGeneric<>( value); } //----------------------------------------------------------------------- /** * Sets the name. * @param value the new value, not null * @return this, for chaining, not null */ public Builder value(T value) { JodaBeanUtils.notNull(value, "value"); this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGeneric.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmGenericArray.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.impl.direct.DirectPrivateBeanBuilder; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "private", factoryName = "of") public final class ImmGenericArray implements Serializable, ImmutableBean { // note each element on a new line /** The name. */ @PropertyDefinition(validate = "notNull") private final T[] values; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmGenericArray}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmGenericArray.Meta meta() { return ImmGenericArray.Meta.INSTANCE; } /** * The meta-bean for {@code ImmGenericArray}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmGenericArray.Meta metaImmGenericArray(Class cls) { return ImmGenericArray.Meta.INSTANCE; } static { MetaBean.register(ImmGenericArray.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Obtains an instance. * @param the type * @param values the value of the property, not null * @return the instance */ public static ImmGenericArray of( T[] values) { return new ImmGenericArray<>( values); } private ImmGenericArray( T[] values) { JodaBeanUtils.notNull(values, "values"); this.values = values; } @SuppressWarnings("unchecked") @Override public ImmGenericArray.Meta metaBean() { return ImmGenericArray.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public T[] getValues() { return values; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmGenericArray other = (ImmGenericArray) obj; return JodaBeanUtils.equal(this.values, other.values); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(values); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericArray{"); buf.append("values").append('=').append(JodaBeanUtils.toString(values)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmGenericArray}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code values} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty values = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "values", ImmGenericArray.class, Object[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "values"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -823812830: // values return this.values; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new ImmGenericArray.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmGenericArray.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code values} property. * @return the meta-property, not null */ public MetaProperty values() { return values; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -823812830: // values return ((ImmGenericArray) bean).getValues(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmGenericArray}. * @param the type */ private static final class Builder extends DirectPrivateBeanBuilder> { private T[] values; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -823812830: // values return this.values; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -823812830: // values this.values = (T[]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public ImmGenericArray build() { return new ImmGenericArray<>( values); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericArray.Builder{"); buf.append("values").append('=').append(JodaBeanUtils.toString(values)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmGenericCollections.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableMap; /** * Immutable bean with nested generic types, used for testing. */ @BeanDefinition public class ImmGenericCollections implements ImmutableBean { @PropertyDefinition(validate = "notNull") private final ImmutableMap map; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmGenericCollections}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmGenericCollections.Meta meta() { return ImmGenericCollections.Meta.INSTANCE; } /** * The meta-bean for {@code ImmGenericCollections}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmGenericCollections.Meta metaImmGenericCollections(Class cls) { return ImmGenericCollections.Meta.INSTANCE; } static { MetaBean.register(ImmGenericCollections.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static ImmGenericCollections.Builder builder() { return new ImmGenericCollections.Builder<>(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected ImmGenericCollections(ImmGenericCollections.Builder builder) { JodaBeanUtils.notNull(builder.map, "map"); this.map = ImmutableMap.copyOf(builder.map); } @SuppressWarnings("unchecked") @Override public ImmGenericCollections.Meta metaBean() { return ImmGenericCollections.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the map. * @return the value of the property, not null */ public ImmutableMap getMap() { return map; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmGenericCollections other = (ImmGenericCollections) obj; return JodaBeanUtils.equal(this.map, other.map); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(map); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericCollections{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("map").append('=').append(JodaBeanUtils.toString(map)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmGenericCollections}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code map} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> map = DirectMetaProperty.ofImmutable( this, "map", ImmGenericCollections.class, (Class) ImmutableMap.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "map"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 107868: // map return this.map; } return super.metaPropertyGet(propertyName); } @Override public ImmGenericCollections.Builder builder() { return new ImmGenericCollections.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmGenericCollections.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code map} property. * @return the meta-property, not null */ public final MetaProperty> map() { return map; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 107868: // map return ((ImmGenericCollections) bean).getMap(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmGenericCollections}. * @param the type */ public static class Builder extends DirectFieldsBeanBuilder> { private Map map = ImmutableMap.of(); /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(ImmGenericCollections beanToCopy) { this.map = beanToCopy.getMap(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 107868: // map return this.map; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 107868: // map this.map = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmGenericCollections build() { return new ImmGenericCollections<>(this); } //----------------------------------------------------------------------- /** * Sets the map. * @param map the new value, not null * @return this, for chaining, not null */ public Builder map(Map map) { JodaBeanUtils.notNull(map, "map"); this.map = map; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericCollections.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("map").append('=').append(JodaBeanUtils.toString(map)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmGenericLinkedRefs.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class ImmGenericLinkedRefs> implements ImmutableBean { // two generic types are linked /** The name. */ @PropertyDefinition(validate = "notNull") private final A value; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmGenericLinkedRefs}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmGenericLinkedRefs.Meta meta() { return ImmGenericLinkedRefs.Meta.INSTANCE; } /** * The meta-bean for {@code ImmGenericLinkedRefs}. * @param the first generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static > ImmGenericLinkedRefs.Meta metaImmGenericLinkedRefs(Class cls1, Class cls2) { return ImmGenericLinkedRefs.Meta.INSTANCE; } static { MetaBean.register(ImmGenericLinkedRefs.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @param the type * @return the builder, not null */ public static > ImmGenericLinkedRefs.Builder builder() { return new ImmGenericLinkedRefs.Builder<>(); } private ImmGenericLinkedRefs( A value) { JodaBeanUtils.notNull(value, "value"); this.value = value; } @SuppressWarnings("unchecked") @Override public ImmGenericLinkedRefs.Meta metaBean() { return ImmGenericLinkedRefs.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public A getValue() { return value; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmGenericLinkedRefs other = (ImmGenericLinkedRefs) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericLinkedRefs{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmGenericLinkedRefs}. * @param the type * @param the type */ public static final class Meta> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty value = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "value", ImmGenericLinkedRefs.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmGenericLinkedRefs.Builder builder() { return new ImmGenericLinkedRefs.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmGenericLinkedRefs.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmGenericLinkedRefs) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmGenericLinkedRefs}. * @param the type * @param the type */ public static final class Builder> extends DirectFieldsBeanBuilder> { private A value; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmGenericLinkedRefs beanToCopy) { this.value = beanToCopy.getValue(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (A) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmGenericLinkedRefs build() { return new ImmGenericLinkedRefs<>( value); } //----------------------------------------------------------------------- /** * Sets the name. * @param value the new value, not null * @return this, for chaining, not null */ public Builder value(A value) { JodaBeanUtils.notNull(value, "value"); this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericLinkedRefs.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmGenericNonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public class ImmGenericNonFinal implements ImmutableBean { /** The name. */ @PropertyDefinition(validate = "notNull") private final T value; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmGenericNonFinal}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmGenericNonFinal.Meta meta() { return ImmGenericNonFinal.Meta.INSTANCE; } /** * The meta-bean for {@code ImmGenericNonFinal}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmGenericNonFinal.Meta metaImmGenericNonFinal(Class cls) { return ImmGenericNonFinal.Meta.INSTANCE; } static { MetaBean.register(ImmGenericNonFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static ImmGenericNonFinal.Builder builder() { return new ImmGenericNonFinal.Builder<>(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected ImmGenericNonFinal(ImmGenericNonFinal.Builder builder) { JodaBeanUtils.notNull(builder.value, "value"); this.value = builder.value; } @SuppressWarnings("unchecked") @Override public ImmGenericNonFinal.Meta metaBean() { return ImmGenericNonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public T getValue() { return value; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmGenericNonFinal other = (ImmGenericNonFinal) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericNonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("value").append('=').append(JodaBeanUtils.toString(value)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmGenericNonFinal}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty value = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "value", ImmGenericNonFinal.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmGenericNonFinal.Builder builder() { return new ImmGenericNonFinal.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmGenericNonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public final MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmGenericNonFinal) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmGenericNonFinal}. * @param the type */ public static class Builder extends DirectFieldsBeanBuilder> { private T value; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(ImmGenericNonFinal beanToCopy) { this.value = beanToCopy.getValue(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (T) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmGenericNonFinal build() { return new ImmGenericNonFinal<>(this); } //----------------------------------------------------------------------- /** * Sets the name. * @param value the new value, not null * @return this, for chaining, not null */ public Builder value(T value) { JodaBeanUtils.notNull(value, "value"); this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmGenericNonFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("value").append('=').append(JodaBeanUtils.toString(value)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmGuava.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMultiset; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableTable; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.SetMultimap; import com.google.common.collect.SortedMultiset; import com.google.common.collect.Table; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public", constructorScope = "public") public final class ImmGuava> implements ImmutableBean { @PropertyDefinition(validate = "notNull") private final ImmutableCollection collection; @PropertyDefinition(validate = "notNull") private final ImmutableList list; @PropertyDefinition(validate = "notNull") private final ImmutableSet set; @PropertyDefinition(validate = "notNull") private final ImmutableSortedSet sortedSet; @PropertyDefinition(validate = "notNull") private final ImmutableMap map; @PropertyDefinition(validate = "notNull") private final ImmutableSortedMap sortedMap; @PropertyDefinition(validate = "notNull") private final ImmutableBiMap biMap; @PropertyDefinition(validate = "notNull") private final ImmutableMultimap multimap; @PropertyDefinition(validate = "notNull") private final ImmutableListMultimap listMultimap; @PropertyDefinition(validate = "notNull") private final ImmutableSetMultimap setMultimap; @PropertyDefinition(validate = "notNull") private final ImmutableMultiset multiset; @PropertyDefinition(validate = "notNull") private final ImmutableSortedMultiset sortedMultiset; @PropertyDefinition(validate = "notNull") private final Collection collectionInterface; @PropertyDefinition(validate = "notNull") private final List listInterface; @PropertyDefinition(validate = "notNull") private final Set setInterface; @PropertyDefinition(validate = "notNull") private final SortedSet sortedSetInterface; @PropertyDefinition(validate = "notNull") private final Map mapInterface; @PropertyDefinition(validate = "notNull") private final SortedMap sortedMapInterface; @PropertyDefinition(validate = "notNull") private final BiMap biMapInterface; @PropertyDefinition(validate = "notNull") private final Multimap multimapInterface; @PropertyDefinition(validate = "notNull") private final ListMultimap listMultimapInterface; @PropertyDefinition(validate = "notNull") private final SetMultimap setMultimapInterface; @PropertyDefinition(validate = "notNull") private final Multiset multisetInterface; @PropertyDefinition(validate = "notNull") private final SortedMultiset sortedMultisetInterface; @PropertyDefinition(validate = "notNull") private final ImmutableList listWildExtendsT; @PropertyDefinition(validate = "notNull") private final ImmutableList listWildExtendsNumber; @PropertyDefinition(validate = "notNull") private final ImmutableList> listWildExtendsComparable; @PropertyDefinition(validate = "notNull") private final ImmutableSet setWildExtendsT; @PropertyDefinition(validate = "notNull") private final ImmutableSet setWildExtendsNumber; @PropertyDefinition(validate = "notNull") private final ImmutableSet> setWildExtendsComparable; // @PropertyDefinition(validate = "notNull") // private final ArrayListMultimap listMultimapArray; // @PropertyDefinition(validate = "notNull") // private final LinkedListMultimap listMultimapLinked; // @PropertyDefinition(validate = "notNull") // private final HashMultimap setMultimapHash; // @PropertyDefinition(validate = "notNull") // private final LinkedHashMultimap setMultimapLinkedHash; @PropertyDefinition(validate = "notNull", builderType = "List") private final ImmutableList listWildBuilder1; @PropertyDefinition(validate = "notNull", builderType = "List") private final ImmutableList
listWildBuilder2; @PropertyDefinition(validate = "notNull", builderType = "Map") private final ImmutableMap mapWildBuilder1; @PropertyDefinition(validate = "notNull") private final ImmutableMap mapWildKey; @PropertyDefinition(validate = "notNull") private final ImmutableTable table; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmGuava}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmGuava.Meta meta() { return ImmGuava.Meta.INSTANCE; } /** * The meta-bean for {@code ImmGuava}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static > ImmGuava.Meta metaImmGuava(Class cls) { return ImmGuava.Meta.INSTANCE; } static { MetaBean.register(ImmGuava.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static > ImmGuava.Builder builder() { return new ImmGuava.Builder<>(); } /** * Creates an instance. * @param collection the value of the property, not null * @param list the value of the property, not null * @param set the value of the property, not null * @param sortedSet the value of the property, not null * @param map the value of the property, not null * @param sortedMap the value of the property, not null * @param biMap the value of the property, not null * @param multimap the value of the property, not null * @param listMultimap the value of the property, not null * @param setMultimap the value of the property, not null * @param multiset the value of the property, not null * @param sortedMultiset the value of the property, not null * @param collectionInterface the value of the property, not null * @param listInterface the value of the property, not null * @param setInterface the value of the property, not null * @param sortedSetInterface the value of the property, not null * @param mapInterface the value of the property, not null * @param sortedMapInterface the value of the property, not null * @param biMapInterface the value of the property, not null * @param multimapInterface the value of the property, not null * @param listMultimapInterface the value of the property, not null * @param setMultimapInterface the value of the property, not null * @param multisetInterface the value of the property, not null * @param sortedMultisetInterface the value of the property, not null * @param listWildExtendsT the value of the property, not null * @param listWildExtendsNumber the value of the property, not null * @param listWildExtendsComparable the value of the property, not null * @param setWildExtendsT the value of the property, not null * @param setWildExtendsNumber the value of the property, not null * @param setWildExtendsComparable the value of the property, not null * @param listWildBuilder1 the value of the property, not null * @param listWildBuilder2 the value of the property, not null * @param mapWildBuilder1 the value of the property, not null * @param mapWildKey the value of the property, not null * @param table the value of the property, not null */ public ImmGuava( Collection collection, List list, Set set, SortedSet sortedSet, Map map, SortedMap sortedMap, BiMap biMap, Multimap multimap, ListMultimap listMultimap, SetMultimap setMultimap, Multiset multiset, SortedMultiset sortedMultiset, Collection collectionInterface, List listInterface, Set setInterface, SortedSet sortedSetInterface, Map mapInterface, SortedMap sortedMapInterface, BiMap biMapInterface, Multimap multimapInterface, ListMultimap listMultimapInterface, SetMultimap setMultimapInterface, Multiset multisetInterface, SortedMultiset sortedMultisetInterface, List listWildExtendsT, List listWildExtendsNumber, List> listWildExtendsComparable, Set setWildExtendsT, Set setWildExtendsNumber, Set> setWildExtendsComparable, List listWildBuilder1, List listWildBuilder2, Map mapWildBuilder1, Map mapWildKey, Table table) { JodaBeanUtils.notNull(collection, "collection"); JodaBeanUtils.notNull(list, "list"); JodaBeanUtils.notNull(set, "set"); JodaBeanUtils.notNull(sortedSet, "sortedSet"); JodaBeanUtils.notNull(map, "map"); JodaBeanUtils.notNull(sortedMap, "sortedMap"); JodaBeanUtils.notNull(biMap, "biMap"); JodaBeanUtils.notNull(multimap, "multimap"); JodaBeanUtils.notNull(listMultimap, "listMultimap"); JodaBeanUtils.notNull(setMultimap, "setMultimap"); JodaBeanUtils.notNull(multiset, "multiset"); JodaBeanUtils.notNull(sortedMultiset, "sortedMultiset"); JodaBeanUtils.notNull(collectionInterface, "collectionInterface"); JodaBeanUtils.notNull(listInterface, "listInterface"); JodaBeanUtils.notNull(setInterface, "setInterface"); JodaBeanUtils.notNull(sortedSetInterface, "sortedSetInterface"); JodaBeanUtils.notNull(mapInterface, "mapInterface"); JodaBeanUtils.notNull(sortedMapInterface, "sortedMapInterface"); JodaBeanUtils.notNull(biMapInterface, "biMapInterface"); JodaBeanUtils.notNull(multimapInterface, "multimapInterface"); JodaBeanUtils.notNull(listMultimapInterface, "listMultimapInterface"); JodaBeanUtils.notNull(setMultimapInterface, "setMultimapInterface"); JodaBeanUtils.notNull(multisetInterface, "multisetInterface"); JodaBeanUtils.notNull(sortedMultisetInterface, "sortedMultisetInterface"); JodaBeanUtils.notNull(listWildExtendsT, "listWildExtendsT"); JodaBeanUtils.notNull(listWildExtendsNumber, "listWildExtendsNumber"); JodaBeanUtils.notNull(listWildExtendsComparable, "listWildExtendsComparable"); JodaBeanUtils.notNull(setWildExtendsT, "setWildExtendsT"); JodaBeanUtils.notNull(setWildExtendsNumber, "setWildExtendsNumber"); JodaBeanUtils.notNull(setWildExtendsComparable, "setWildExtendsComparable"); JodaBeanUtils.notNull(listWildBuilder1, "listWildBuilder1"); JodaBeanUtils.notNull(listWildBuilder2, "listWildBuilder2"); JodaBeanUtils.notNull(mapWildBuilder1, "mapWildBuilder1"); JodaBeanUtils.notNull(mapWildKey, "mapWildKey"); JodaBeanUtils.notNull(table, "table"); this.collection = ImmutableList.copyOf(collection); this.list = ImmutableList.copyOf(list); this.set = ImmutableSet.copyOf(set); this.sortedSet = ImmutableSortedSet.copyOfSorted(sortedSet); this.map = ImmutableMap.copyOf(map); this.sortedMap = ImmutableSortedMap.copyOfSorted(sortedMap); this.biMap = ImmutableBiMap.copyOf(biMap); this.multimap = ImmutableMultimap.copyOf(multimap); this.listMultimap = ImmutableListMultimap.copyOf(listMultimap); this.setMultimap = ImmutableSetMultimap.copyOf(setMultimap); this.multiset = ImmutableMultiset.copyOf(multiset); this.sortedMultiset = ImmutableSortedMultiset.copyOfSorted(sortedMultiset); this.collectionInterface = ImmutableList.copyOf(collectionInterface); this.listInterface = ImmutableList.copyOf(listInterface); this.setInterface = ImmutableSet.copyOf(setInterface); this.sortedSetInterface = ImmutableSortedSet.copyOfSorted(sortedSetInterface); this.mapInterface = ImmutableMap.copyOf(mapInterface); this.sortedMapInterface = ImmutableSortedMap.copyOfSorted(sortedMapInterface); this.biMapInterface = ImmutableBiMap.copyOf(biMapInterface); this.multimapInterface = ImmutableMultimap.copyOf(multimapInterface); this.listMultimapInterface = ImmutableListMultimap.copyOf(listMultimapInterface); this.setMultimapInterface = ImmutableSetMultimap.copyOf(setMultimapInterface); this.multisetInterface = ImmutableMultiset.copyOf(multisetInterface); this.sortedMultisetInterface = ImmutableSortedMultiset.copyOfSorted(sortedMultisetInterface); this.listWildExtendsT = ImmutableList.copyOf(listWildExtendsT); this.listWildExtendsNumber = ImmutableList.copyOf(listWildExtendsNumber); this.listWildExtendsComparable = ImmutableList.copyOf(listWildExtendsComparable); this.setWildExtendsT = ImmutableSet.copyOf(setWildExtendsT); this.setWildExtendsNumber = ImmutableSet.copyOf(setWildExtendsNumber); this.setWildExtendsComparable = ImmutableSet.copyOf(setWildExtendsComparable); this.listWildBuilder1 = ImmutableList.copyOf(listWildBuilder1); this.listWildBuilder2 = ImmutableList.copyOf(listWildBuilder2); this.mapWildBuilder1 = ImmutableMap.copyOf(mapWildBuilder1); this.mapWildKey = ImmutableMap.copyOf(mapWildKey); this.table = ImmutableTable.copyOf(table); } @SuppressWarnings("unchecked") @Override public ImmGuava.Meta metaBean() { return ImmGuava.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the collection. * @return the value of the property, not null */ public ImmutableCollection getCollection() { return collection; } //----------------------------------------------------------------------- /** * Gets the list. * @return the value of the property, not null */ public ImmutableList getList() { return list; } //----------------------------------------------------------------------- /** * Gets the set. * @return the value of the property, not null */ public ImmutableSet getSet() { return set; } //----------------------------------------------------------------------- /** * Gets the sortedSet. * @return the value of the property, not null */ public ImmutableSortedSet getSortedSet() { return sortedSet; } //----------------------------------------------------------------------- /** * Gets the map. * @return the value of the property, not null */ public ImmutableMap getMap() { return map; } //----------------------------------------------------------------------- /** * Gets the sortedMap. * @return the value of the property, not null */ public ImmutableSortedMap getSortedMap() { return sortedMap; } //----------------------------------------------------------------------- /** * Gets the biMap. * @return the value of the property, not null */ public ImmutableBiMap getBiMap() { return biMap; } //----------------------------------------------------------------------- /** * Gets the multimap. * @return the value of the property, not null */ public ImmutableMultimap getMultimap() { return multimap; } //----------------------------------------------------------------------- /** * Gets the listMultimap. * @return the value of the property, not null */ public ImmutableListMultimap getListMultimap() { return listMultimap; } //----------------------------------------------------------------------- /** * Gets the setMultimap. * @return the value of the property, not null */ public ImmutableSetMultimap getSetMultimap() { return setMultimap; } //----------------------------------------------------------------------- /** * Gets the multiset. * @return the value of the property, not null */ public ImmutableMultiset getMultiset() { return multiset; } //----------------------------------------------------------------------- /** * Gets the sortedMultiset. * @return the value of the property, not null */ public ImmutableSortedMultiset getSortedMultiset() { return sortedMultiset; } //----------------------------------------------------------------------- /** * Gets the collectionInterface. * @return the value of the property, not null */ public Collection getCollectionInterface() { return collectionInterface; } //----------------------------------------------------------------------- /** * Gets the listInterface. * @return the value of the property, not null */ public List getListInterface() { return listInterface; } //----------------------------------------------------------------------- /** * Gets the setInterface. * @return the value of the property, not null */ public Set getSetInterface() { return setInterface; } //----------------------------------------------------------------------- /** * Gets the sortedSetInterface. * @return the value of the property, not null */ public SortedSet getSortedSetInterface() { return sortedSetInterface; } //----------------------------------------------------------------------- /** * Gets the mapInterface. * @return the value of the property, not null */ public Map getMapInterface() { return mapInterface; } //----------------------------------------------------------------------- /** * Gets the sortedMapInterface. * @return the value of the property, not null */ public SortedMap getSortedMapInterface() { return sortedMapInterface; } //----------------------------------------------------------------------- /** * Gets the biMapInterface. * @return the value of the property, not null */ public BiMap getBiMapInterface() { return biMapInterface; } //----------------------------------------------------------------------- /** * Gets the multimapInterface. * @return the value of the property, not null */ public Multimap getMultimapInterface() { return multimapInterface; } //----------------------------------------------------------------------- /** * Gets the listMultimapInterface. * @return the value of the property, not null */ public ListMultimap getListMultimapInterface() { return listMultimapInterface; } //----------------------------------------------------------------------- /** * Gets the setMultimapInterface. * @return the value of the property, not null */ public SetMultimap getSetMultimapInterface() { return setMultimapInterface; } //----------------------------------------------------------------------- /** * Gets the multisetInterface. * @return the value of the property, not null */ public Multiset getMultisetInterface() { return multisetInterface; } //----------------------------------------------------------------------- /** * Gets the sortedMultisetInterface. * @return the value of the property, not null */ public SortedMultiset getSortedMultisetInterface() { return sortedMultisetInterface; } //----------------------------------------------------------------------- /** * Gets the listWildExtendsT. * @return the value of the property, not null */ public ImmutableList getListWildExtendsT() { return listWildExtendsT; } //----------------------------------------------------------------------- /** * Gets the listWildExtendsNumber. * @return the value of the property, not null */ public ImmutableList getListWildExtendsNumber() { return listWildExtendsNumber; } //----------------------------------------------------------------------- /** * Gets the listWildExtendsComparable. * @return the value of the property, not null */ public ImmutableList> getListWildExtendsComparable() { return listWildExtendsComparable; } //----------------------------------------------------------------------- /** * Gets the setWildExtendsT. * @return the value of the property, not null */ public ImmutableSet getSetWildExtendsT() { return setWildExtendsT; } //----------------------------------------------------------------------- /** * Gets the setWildExtendsNumber. * @return the value of the property, not null */ public ImmutableSet getSetWildExtendsNumber() { return setWildExtendsNumber; } //----------------------------------------------------------------------- /** * Gets the setWildExtendsComparable. * @return the value of the property, not null */ public ImmutableSet> getSetWildExtendsComparable() { return setWildExtendsComparable; } //----------------------------------------------------------------------- /** * Gets the listWildBuilder1. * @return the value of the property, not null */ public ImmutableList getListWildBuilder1() { return listWildBuilder1; } //----------------------------------------------------------------------- /** * Gets the listWildBuilder2. * @return the value of the property, not null */ public ImmutableList
getListWildBuilder2() { return listWildBuilder2; } //----------------------------------------------------------------------- /** * Gets the mapWildBuilder1. * @return the value of the property, not null */ public ImmutableMap getMapWildBuilder1() { return mapWildBuilder1; } //----------------------------------------------------------------------- /** * Gets the mapWildKey. * @return the value of the property, not null */ public ImmutableMap getMapWildKey() { return mapWildKey; } //----------------------------------------------------------------------- /** * Gets the table. * @return the value of the property, not null */ public ImmutableTable getTable() { return table; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmGuava other = (ImmGuava) obj; return JodaBeanUtils.equal(this.collection, other.collection) && JodaBeanUtils.equal(this.list, other.list) && JodaBeanUtils.equal(this.set, other.set) && JodaBeanUtils.equal(this.sortedSet, other.sortedSet) && JodaBeanUtils.equal(this.map, other.map) && JodaBeanUtils.equal(this.sortedMap, other.sortedMap) && JodaBeanUtils.equal(this.biMap, other.biMap) && JodaBeanUtils.equal(this.multimap, other.multimap) && JodaBeanUtils.equal(this.listMultimap, other.listMultimap) && JodaBeanUtils.equal(this.setMultimap, other.setMultimap) && JodaBeanUtils.equal(this.multiset, other.multiset) && JodaBeanUtils.equal(this.sortedMultiset, other.sortedMultiset) && JodaBeanUtils.equal(this.collectionInterface, other.collectionInterface) && JodaBeanUtils.equal(this.listInterface, other.listInterface) && JodaBeanUtils.equal(this.setInterface, other.setInterface) && JodaBeanUtils.equal(this.sortedSetInterface, other.sortedSetInterface) && JodaBeanUtils.equal(this.mapInterface, other.mapInterface) && JodaBeanUtils.equal(this.sortedMapInterface, other.sortedMapInterface) && JodaBeanUtils.equal(this.biMapInterface, other.biMapInterface) && JodaBeanUtils.equal(this.multimapInterface, other.multimapInterface) && JodaBeanUtils.equal(this.listMultimapInterface, other.listMultimapInterface) && JodaBeanUtils.equal(this.setMultimapInterface, other.setMultimapInterface) && JodaBeanUtils.equal(this.multisetInterface, other.multisetInterface) && JodaBeanUtils.equal(this.sortedMultisetInterface, other.sortedMultisetInterface) && JodaBeanUtils.equal(this.listWildExtendsT, other.listWildExtendsT) && JodaBeanUtils.equal(this.listWildExtendsNumber, other.listWildExtendsNumber) && JodaBeanUtils.equal(this.listWildExtendsComparable, other.listWildExtendsComparable) && JodaBeanUtils.equal(this.setWildExtendsT, other.setWildExtendsT) && JodaBeanUtils.equal(this.setWildExtendsNumber, other.setWildExtendsNumber) && JodaBeanUtils.equal(this.setWildExtendsComparable, other.setWildExtendsComparable) && JodaBeanUtils.equal(this.listWildBuilder1, other.listWildBuilder1) && JodaBeanUtils.equal(this.listWildBuilder2, other.listWildBuilder2) && JodaBeanUtils.equal(this.mapWildBuilder1, other.mapWildBuilder1) && JodaBeanUtils.equal(this.mapWildKey, other.mapWildKey) && JodaBeanUtils.equal(this.table, other.table); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(collection); hash = hash * 31 + JodaBeanUtils.hashCode(list); hash = hash * 31 + JodaBeanUtils.hashCode(set); hash = hash * 31 + JodaBeanUtils.hashCode(sortedSet); hash = hash * 31 + JodaBeanUtils.hashCode(map); hash = hash * 31 + JodaBeanUtils.hashCode(sortedMap); hash = hash * 31 + JodaBeanUtils.hashCode(biMap); hash = hash * 31 + JodaBeanUtils.hashCode(multimap); hash = hash * 31 + JodaBeanUtils.hashCode(listMultimap); hash = hash * 31 + JodaBeanUtils.hashCode(setMultimap); hash = hash * 31 + JodaBeanUtils.hashCode(multiset); hash = hash * 31 + JodaBeanUtils.hashCode(sortedMultiset); hash = hash * 31 + JodaBeanUtils.hashCode(collectionInterface); hash = hash * 31 + JodaBeanUtils.hashCode(listInterface); hash = hash * 31 + JodaBeanUtils.hashCode(setInterface); hash = hash * 31 + JodaBeanUtils.hashCode(sortedSetInterface); hash = hash * 31 + JodaBeanUtils.hashCode(mapInterface); hash = hash * 31 + JodaBeanUtils.hashCode(sortedMapInterface); hash = hash * 31 + JodaBeanUtils.hashCode(biMapInterface); hash = hash * 31 + JodaBeanUtils.hashCode(multimapInterface); hash = hash * 31 + JodaBeanUtils.hashCode(listMultimapInterface); hash = hash * 31 + JodaBeanUtils.hashCode(setMultimapInterface); hash = hash * 31 + JodaBeanUtils.hashCode(multisetInterface); hash = hash * 31 + JodaBeanUtils.hashCode(sortedMultisetInterface); hash = hash * 31 + JodaBeanUtils.hashCode(listWildExtendsT); hash = hash * 31 + JodaBeanUtils.hashCode(listWildExtendsNumber); hash = hash * 31 + JodaBeanUtils.hashCode(listWildExtendsComparable); hash = hash * 31 + JodaBeanUtils.hashCode(setWildExtendsT); hash = hash * 31 + JodaBeanUtils.hashCode(setWildExtendsNumber); hash = hash * 31 + JodaBeanUtils.hashCode(setWildExtendsComparable); hash = hash * 31 + JodaBeanUtils.hashCode(listWildBuilder1); hash = hash * 31 + JodaBeanUtils.hashCode(listWildBuilder2); hash = hash * 31 + JodaBeanUtils.hashCode(mapWildBuilder1); hash = hash * 31 + JodaBeanUtils.hashCode(mapWildKey); hash = hash * 31 + JodaBeanUtils.hashCode(table); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(1152); buf.append("ImmGuava{"); buf.append("collection").append('=').append(JodaBeanUtils.toString(collection)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("set").append('=').append(JodaBeanUtils.toString(set)).append(',').append(' '); buf.append("sortedSet").append('=').append(JodaBeanUtils.toString(sortedSet)).append(',').append(' '); buf.append("map").append('=').append(JodaBeanUtils.toString(map)).append(',').append(' '); buf.append("sortedMap").append('=').append(JodaBeanUtils.toString(sortedMap)).append(',').append(' '); buf.append("biMap").append('=').append(JodaBeanUtils.toString(biMap)).append(',').append(' '); buf.append("multimap").append('=').append(JodaBeanUtils.toString(multimap)).append(',').append(' '); buf.append("listMultimap").append('=').append(JodaBeanUtils.toString(listMultimap)).append(',').append(' '); buf.append("setMultimap").append('=').append(JodaBeanUtils.toString(setMultimap)).append(',').append(' '); buf.append("multiset").append('=').append(JodaBeanUtils.toString(multiset)).append(',').append(' '); buf.append("sortedMultiset").append('=').append(JodaBeanUtils.toString(sortedMultiset)).append(',').append(' '); buf.append("collectionInterface").append('=').append(JodaBeanUtils.toString(collectionInterface)).append(',').append(' '); buf.append("listInterface").append('=').append(JodaBeanUtils.toString(listInterface)).append(',').append(' '); buf.append("setInterface").append('=').append(JodaBeanUtils.toString(setInterface)).append(',').append(' '); buf.append("sortedSetInterface").append('=').append(JodaBeanUtils.toString(sortedSetInterface)).append(',').append(' '); buf.append("mapInterface").append('=').append(JodaBeanUtils.toString(mapInterface)).append(',').append(' '); buf.append("sortedMapInterface").append('=').append(JodaBeanUtils.toString(sortedMapInterface)).append(',').append(' '); buf.append("biMapInterface").append('=').append(JodaBeanUtils.toString(biMapInterface)).append(',').append(' '); buf.append("multimapInterface").append('=').append(JodaBeanUtils.toString(multimapInterface)).append(',').append(' '); buf.append("listMultimapInterface").append('=').append(JodaBeanUtils.toString(listMultimapInterface)).append(',').append(' '); buf.append("setMultimapInterface").append('=').append(JodaBeanUtils.toString(setMultimapInterface)).append(',').append(' '); buf.append("multisetInterface").append('=').append(JodaBeanUtils.toString(multisetInterface)).append(',').append(' '); buf.append("sortedMultisetInterface").append('=').append(JodaBeanUtils.toString(sortedMultisetInterface)).append(',').append(' '); buf.append("listWildExtendsT").append('=').append(JodaBeanUtils.toString(listWildExtendsT)).append(',').append(' '); buf.append("listWildExtendsNumber").append('=').append(JodaBeanUtils.toString(listWildExtendsNumber)).append(',').append(' '); buf.append("listWildExtendsComparable").append('=').append(JodaBeanUtils.toString(listWildExtendsComparable)).append(',').append(' '); buf.append("setWildExtendsT").append('=').append(JodaBeanUtils.toString(setWildExtendsT)).append(',').append(' '); buf.append("setWildExtendsNumber").append('=').append(JodaBeanUtils.toString(setWildExtendsNumber)).append(',').append(' '); buf.append("setWildExtendsComparable").append('=').append(JodaBeanUtils.toString(setWildExtendsComparable)).append(',').append(' '); buf.append("listWildBuilder1").append('=').append(JodaBeanUtils.toString(listWildBuilder1)).append(',').append(' '); buf.append("listWildBuilder2").append('=').append(JodaBeanUtils.toString(listWildBuilder2)).append(',').append(' '); buf.append("mapWildBuilder1").append('=').append(JodaBeanUtils.toString(mapWildBuilder1)).append(',').append(' '); buf.append("mapWildKey").append('=').append(JodaBeanUtils.toString(mapWildKey)).append(',').append(' '); buf.append("table").append('=').append(JodaBeanUtils.toString(table)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmGuava}. * @param the type */ public static final class Meta> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code collection} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> collection = DirectMetaProperty.ofImmutable( this, "collection", ImmGuava.class, (Class) ImmutableCollection.class); /** * The meta-property for the {@code list} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> list = DirectMetaProperty.ofImmutable( this, "list", ImmGuava.class, (Class) ImmutableList.class); /** * The meta-property for the {@code set} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> set = DirectMetaProperty.ofImmutable( this, "set", ImmGuava.class, (Class) ImmutableSet.class); /** * The meta-property for the {@code sortedSet} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sortedSet = DirectMetaProperty.ofImmutable( this, "sortedSet", ImmGuava.class, (Class) ImmutableSortedSet.class); /** * The meta-property for the {@code map} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> map = DirectMetaProperty.ofImmutable( this, "map", ImmGuava.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code sortedMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sortedMap = DirectMetaProperty.ofImmutable( this, "sortedMap", ImmGuava.class, (Class) ImmutableSortedMap.class); /** * The meta-property for the {@code biMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> biMap = DirectMetaProperty.ofImmutable( this, "biMap", ImmGuava.class, (Class) ImmutableBiMap.class); /** * The meta-property for the {@code multimap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> multimap = DirectMetaProperty.ofImmutable( this, "multimap", ImmGuava.class, (Class) ImmutableMultimap.class); /** * The meta-property for the {@code listMultimap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listMultimap = DirectMetaProperty.ofImmutable( this, "listMultimap", ImmGuava.class, (Class) ImmutableListMultimap.class); /** * The meta-property for the {@code setMultimap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> setMultimap = DirectMetaProperty.ofImmutable( this, "setMultimap", ImmGuava.class, (Class) ImmutableSetMultimap.class); /** * The meta-property for the {@code multiset} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> multiset = DirectMetaProperty.ofImmutable( this, "multiset", ImmGuava.class, (Class) ImmutableMultiset.class); /** * The meta-property for the {@code sortedMultiset} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sortedMultiset = DirectMetaProperty.ofImmutable( this, "sortedMultiset", ImmGuava.class, (Class) ImmutableSortedMultiset.class); /** * The meta-property for the {@code collectionInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> collectionInterface = DirectMetaProperty.ofImmutable( this, "collectionInterface", ImmGuava.class, (Class) Collection.class); /** * The meta-property for the {@code listInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listInterface = DirectMetaProperty.ofImmutable( this, "listInterface", ImmGuava.class, (Class) List.class); /** * The meta-property for the {@code setInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> setInterface = DirectMetaProperty.ofImmutable( this, "setInterface", ImmGuava.class, (Class) Set.class); /** * The meta-property for the {@code sortedSetInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sortedSetInterface = DirectMetaProperty.ofImmutable( this, "sortedSetInterface", ImmGuava.class, (Class) SortedSet.class); /** * The meta-property for the {@code mapInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> mapInterface = DirectMetaProperty.ofImmutable( this, "mapInterface", ImmGuava.class, (Class) Map.class); /** * The meta-property for the {@code sortedMapInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sortedMapInterface = DirectMetaProperty.ofImmutable( this, "sortedMapInterface", ImmGuava.class, (Class) SortedMap.class); /** * The meta-property for the {@code biMapInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> biMapInterface = DirectMetaProperty.ofImmutable( this, "biMapInterface", ImmGuava.class, (Class) BiMap.class); /** * The meta-property for the {@code multimapInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> multimapInterface = DirectMetaProperty.ofImmutable( this, "multimapInterface", ImmGuava.class, (Class) Multimap.class); /** * The meta-property for the {@code listMultimapInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listMultimapInterface = DirectMetaProperty.ofImmutable( this, "listMultimapInterface", ImmGuava.class, (Class) ListMultimap.class); /** * The meta-property for the {@code setMultimapInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> setMultimapInterface = DirectMetaProperty.ofImmutable( this, "setMultimapInterface", ImmGuava.class, (Class) SetMultimap.class); /** * The meta-property for the {@code multisetInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> multisetInterface = DirectMetaProperty.ofImmutable( this, "multisetInterface", ImmGuava.class, (Class) Multiset.class); /** * The meta-property for the {@code sortedMultisetInterface} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> sortedMultisetInterface = DirectMetaProperty.ofImmutable( this, "sortedMultisetInterface", ImmGuava.class, (Class) SortedMultiset.class); /** * The meta-property for the {@code listWildExtendsT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildExtendsT = DirectMetaProperty.ofImmutable( this, "listWildExtendsT", ImmGuava.class, (Class) ImmutableList.class); /** * The meta-property for the {@code listWildExtendsNumber} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildExtendsNumber = DirectMetaProperty.ofImmutable( this, "listWildExtendsNumber", ImmGuava.class, (Class) ImmutableList.class); /** * The meta-property for the {@code listWildExtendsComparable} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> listWildExtendsComparable = DirectMetaProperty.ofImmutable( this, "listWildExtendsComparable", ImmGuava.class, (Class) ImmutableList.class); /** * The meta-property for the {@code setWildExtendsT} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> setWildExtendsT = DirectMetaProperty.ofImmutable( this, "setWildExtendsT", ImmGuava.class, (Class) ImmutableSet.class); /** * The meta-property for the {@code setWildExtendsNumber} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> setWildExtendsNumber = DirectMetaProperty.ofImmutable( this, "setWildExtendsNumber", ImmGuava.class, (Class) ImmutableSet.class); /** * The meta-property for the {@code setWildExtendsComparable} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> setWildExtendsComparable = DirectMetaProperty.ofImmutable( this, "setWildExtendsComparable", ImmGuava.class, (Class) ImmutableSet.class); /** * The meta-property for the {@code listWildBuilder1} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildBuilder1 = DirectMetaProperty.ofImmutable( this, "listWildBuilder1", ImmGuava.class, (Class) ImmutableList.class); /** * The meta-property for the {@code listWildBuilder2} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildBuilder2 = DirectMetaProperty.ofImmutable( this, "listWildBuilder2", ImmGuava.class, (Class) ImmutableList.class); /** * The meta-property for the {@code mapWildBuilder1} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> mapWildBuilder1 = DirectMetaProperty.ofImmutable( this, "mapWildBuilder1", ImmGuava.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code mapWildKey} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> mapWildKey = DirectMetaProperty.ofImmutable( this, "mapWildKey", ImmGuava.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code table} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> table = DirectMetaProperty.ofImmutable( this, "table", ImmGuava.class, (Class) ImmutableTable.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "collection", "list", "set", "sortedSet", "map", "sortedMap", "biMap", "multimap", "listMultimap", "setMultimap", "multiset", "sortedMultiset", "collectionInterface", "listInterface", "setInterface", "sortedSetInterface", "mapInterface", "sortedMapInterface", "biMapInterface", "multimapInterface", "listMultimapInterface", "setMultimapInterface", "multisetInterface", "sortedMultisetInterface", "listWildExtendsT", "listWildExtendsNumber", "listWildExtendsComparable", "setWildExtendsT", "setWildExtendsNumber", "setWildExtendsComparable", "listWildBuilder1", "listWildBuilder2", "mapWildBuilder1", "mapWildKey", "table"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1741312354: // collection return this.collection; case 3322014: // list return this.list; case 113762: // set return this.set; case -6890395: // sortedSet return this.sortedSet; case 107868: // map return this.map; case -6896289: // sortedMap return this.sortedMap; case 93710229: // biMap return this.biMap; case 653826435: // multimap return this.multimap; case 1737633857: // listMultimap return this.listMultimap; case -1651820539: // setMultimap return this.setMultimap; case 653832329: // multiset return this.multiset; case 1018567270: // sortedMultiset return this.sortedMultiset; case 420048955: // collectionInterface return this.collectionInterface; case -259084741: // listInterface return this.listInterface; case 2042011383: // setInterface return this.setInterface; case 1019335252: // sortedSetInterface return this.sortedSetInterface; case 651439933: // mapInterface return this.mapInterface; case -371236198: // sortedMapInterface return this.sortedMapInterface; case 2068077860: // biMapInterface return this.biMapInterface; case -1415579914: // multimapInterface return this.multimapInterface; case 1576080888: // listMultimapInterface return this.listMultimapInterface; case -630551884: // setMultimapInterface return this.setMultimapInterface; case -25008464: // multisetInterface return this.multisetInterface; case 271697267: // sortedMultisetInterface return this.sortedMultisetInterface; case -826400637: // listWildExtendsT return this.listWildExtendsT; case 789015706: // listWildExtendsNumber return this.listWildExtendsNumber; case 857377195: // listWildExtendsComparable return this.listWildExtendsComparable; case -844782009: // setWildExtendsT return this.setWildExtendsT; case -1417617066: // setWildExtendsNumber return this.setWildExtendsNumber; case 940785767: // setWildExtendsComparable return this.setWildExtendsComparable; case -436161122: // listWildBuilder1 return this.listWildBuilder1; case -436161121: // listWildBuilder2 return this.listWildBuilder2; case -2009039524: // mapWildBuilder1 return this.mapWildBuilder1; case 1463967033: // mapWildKey return this.mapWildKey; case 110115790: // table return this.table; } return super.metaPropertyGet(propertyName); } @Override public ImmGuava.Builder builder() { return new ImmGuava.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmGuava.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code collection} property. * @return the meta-property, not null */ public MetaProperty> collection() { return collection; } /** * The meta-property for the {@code list} property. * @return the meta-property, not null */ public MetaProperty> list() { return list; } /** * The meta-property for the {@code set} property. * @return the meta-property, not null */ public MetaProperty> set() { return set; } /** * The meta-property for the {@code sortedSet} property. * @return the meta-property, not null */ public MetaProperty> sortedSet() { return sortedSet; } /** * The meta-property for the {@code map} property. * @return the meta-property, not null */ public MetaProperty> map() { return map; } /** * The meta-property for the {@code sortedMap} property. * @return the meta-property, not null */ public MetaProperty> sortedMap() { return sortedMap; } /** * The meta-property for the {@code biMap} property. * @return the meta-property, not null */ public MetaProperty> biMap() { return biMap; } /** * The meta-property for the {@code multimap} property. * @return the meta-property, not null */ public MetaProperty> multimap() { return multimap; } /** * The meta-property for the {@code listMultimap} property. * @return the meta-property, not null */ public MetaProperty> listMultimap() { return listMultimap; } /** * The meta-property for the {@code setMultimap} property. * @return the meta-property, not null */ public MetaProperty> setMultimap() { return setMultimap; } /** * The meta-property for the {@code multiset} property. * @return the meta-property, not null */ public MetaProperty> multiset() { return multiset; } /** * The meta-property for the {@code sortedMultiset} property. * @return the meta-property, not null */ public MetaProperty> sortedMultiset() { return sortedMultiset; } /** * The meta-property for the {@code collectionInterface} property. * @return the meta-property, not null */ public MetaProperty> collectionInterface() { return collectionInterface; } /** * The meta-property for the {@code listInterface} property. * @return the meta-property, not null */ public MetaProperty> listInterface() { return listInterface; } /** * The meta-property for the {@code setInterface} property. * @return the meta-property, not null */ public MetaProperty> setInterface() { return setInterface; } /** * The meta-property for the {@code sortedSetInterface} property. * @return the meta-property, not null */ public MetaProperty> sortedSetInterface() { return sortedSetInterface; } /** * The meta-property for the {@code mapInterface} property. * @return the meta-property, not null */ public MetaProperty> mapInterface() { return mapInterface; } /** * The meta-property for the {@code sortedMapInterface} property. * @return the meta-property, not null */ public MetaProperty> sortedMapInterface() { return sortedMapInterface; } /** * The meta-property for the {@code biMapInterface} property. * @return the meta-property, not null */ public MetaProperty> biMapInterface() { return biMapInterface; } /** * The meta-property for the {@code multimapInterface} property. * @return the meta-property, not null */ public MetaProperty> multimapInterface() { return multimapInterface; } /** * The meta-property for the {@code listMultimapInterface} property. * @return the meta-property, not null */ public MetaProperty> listMultimapInterface() { return listMultimapInterface; } /** * The meta-property for the {@code setMultimapInterface} property. * @return the meta-property, not null */ public MetaProperty> setMultimapInterface() { return setMultimapInterface; } /** * The meta-property for the {@code multisetInterface} property. * @return the meta-property, not null */ public MetaProperty> multisetInterface() { return multisetInterface; } /** * The meta-property for the {@code sortedMultisetInterface} property. * @return the meta-property, not null */ public MetaProperty> sortedMultisetInterface() { return sortedMultisetInterface; } /** * The meta-property for the {@code listWildExtendsT} property. * @return the meta-property, not null */ public MetaProperty> listWildExtendsT() { return listWildExtendsT; } /** * The meta-property for the {@code listWildExtendsNumber} property. * @return the meta-property, not null */ public MetaProperty> listWildExtendsNumber() { return listWildExtendsNumber; } /** * The meta-property for the {@code listWildExtendsComparable} property. * @return the meta-property, not null */ public MetaProperty>> listWildExtendsComparable() { return listWildExtendsComparable; } /** * The meta-property for the {@code setWildExtendsT} property. * @return the meta-property, not null */ public MetaProperty> setWildExtendsT() { return setWildExtendsT; } /** * The meta-property for the {@code setWildExtendsNumber} property. * @return the meta-property, not null */ public MetaProperty> setWildExtendsNumber() { return setWildExtendsNumber; } /** * The meta-property for the {@code setWildExtendsComparable} property. * @return the meta-property, not null */ public MetaProperty>> setWildExtendsComparable() { return setWildExtendsComparable; } /** * The meta-property for the {@code listWildBuilder1} property. * @return the meta-property, not null */ public MetaProperty> listWildBuilder1() { return listWildBuilder1; } /** * The meta-property for the {@code listWildBuilder2} property. * @return the meta-property, not null */ public MetaProperty> listWildBuilder2() { return listWildBuilder2; } /** * The meta-property for the {@code mapWildBuilder1} property. * @return the meta-property, not null */ public MetaProperty> mapWildBuilder1() { return mapWildBuilder1; } /** * The meta-property for the {@code mapWildKey} property. * @return the meta-property, not null */ public MetaProperty> mapWildKey() { return mapWildKey; } /** * The meta-property for the {@code table} property. * @return the meta-property, not null */ public MetaProperty> table() { return table; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1741312354: // collection return ((ImmGuava) bean).getCollection(); case 3322014: // list return ((ImmGuava) bean).getList(); case 113762: // set return ((ImmGuava) bean).getSet(); case -6890395: // sortedSet return ((ImmGuava) bean).getSortedSet(); case 107868: // map return ((ImmGuava) bean).getMap(); case -6896289: // sortedMap return ((ImmGuava) bean).getSortedMap(); case 93710229: // biMap return ((ImmGuava) bean).getBiMap(); case 653826435: // multimap return ((ImmGuava) bean).getMultimap(); case 1737633857: // listMultimap return ((ImmGuava) bean).getListMultimap(); case -1651820539: // setMultimap return ((ImmGuava) bean).getSetMultimap(); case 653832329: // multiset return ((ImmGuava) bean).getMultiset(); case 1018567270: // sortedMultiset return ((ImmGuava) bean).getSortedMultiset(); case 420048955: // collectionInterface return ((ImmGuava) bean).getCollectionInterface(); case -259084741: // listInterface return ((ImmGuava) bean).getListInterface(); case 2042011383: // setInterface return ((ImmGuava) bean).getSetInterface(); case 1019335252: // sortedSetInterface return ((ImmGuava) bean).getSortedSetInterface(); case 651439933: // mapInterface return ((ImmGuava) bean).getMapInterface(); case -371236198: // sortedMapInterface return ((ImmGuava) bean).getSortedMapInterface(); case 2068077860: // biMapInterface return ((ImmGuava) bean).getBiMapInterface(); case -1415579914: // multimapInterface return ((ImmGuava) bean).getMultimapInterface(); case 1576080888: // listMultimapInterface return ((ImmGuava) bean).getListMultimapInterface(); case -630551884: // setMultimapInterface return ((ImmGuava) bean).getSetMultimapInterface(); case -25008464: // multisetInterface return ((ImmGuava) bean).getMultisetInterface(); case 271697267: // sortedMultisetInterface return ((ImmGuava) bean).getSortedMultisetInterface(); case -826400637: // listWildExtendsT return ((ImmGuava) bean).getListWildExtendsT(); case 789015706: // listWildExtendsNumber return ((ImmGuava) bean).getListWildExtendsNumber(); case 857377195: // listWildExtendsComparable return ((ImmGuava) bean).getListWildExtendsComparable(); case -844782009: // setWildExtendsT return ((ImmGuava) bean).getSetWildExtendsT(); case -1417617066: // setWildExtendsNumber return ((ImmGuava) bean).getSetWildExtendsNumber(); case 940785767: // setWildExtendsComparable return ((ImmGuava) bean).getSetWildExtendsComparable(); case -436161122: // listWildBuilder1 return ((ImmGuava) bean).getListWildBuilder1(); case -436161121: // listWildBuilder2 return ((ImmGuava) bean).getListWildBuilder2(); case -2009039524: // mapWildBuilder1 return ((ImmGuava) bean).getMapWildBuilder1(); case 1463967033: // mapWildKey return ((ImmGuava) bean).getMapWildKey(); case 110115790: // table return ((ImmGuava) bean).getTable(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmGuava}. * @param the type */ public static final class Builder> extends DirectFieldsBeanBuilder> { private Collection collection = ImmutableList.of(); private List list = ImmutableList.of(); private Set set = ImmutableSet.of(); private SortedSet sortedSet = ImmutableSortedSet.of(); private Map map = ImmutableMap.of(); private SortedMap sortedMap = ImmutableSortedMap.of(); private BiMap biMap = ImmutableBiMap.of(); private Multimap multimap = ImmutableMultimap.of(); private ListMultimap listMultimap = ImmutableListMultimap.of(); private SetMultimap setMultimap = ImmutableSetMultimap.of(); private Multiset multiset = ImmutableMultiset.of(); private SortedMultiset sortedMultiset = ImmutableSortedMultiset.of(); private Collection collectionInterface = ImmutableList.of(); private List listInterface = ImmutableList.of(); private Set setInterface = ImmutableSet.of(); private SortedSet sortedSetInterface = ImmutableSortedSet.of(); private Map mapInterface = ImmutableMap.of(); private SortedMap sortedMapInterface = ImmutableSortedMap.of(); private BiMap biMapInterface = ImmutableBiMap.of(); private Multimap multimapInterface = ImmutableMultimap.of(); private ListMultimap listMultimapInterface = ImmutableListMultimap.of(); private SetMultimap setMultimapInterface = ImmutableSetMultimap.of(); private Multiset multisetInterface = ImmutableMultiset.of(); private SortedMultiset sortedMultisetInterface = ImmutableSortedMultiset.of(); private List listWildExtendsT = ImmutableList.of(); private List listWildExtendsNumber = ImmutableList.of(); private List> listWildExtendsComparable = ImmutableList.of(); private Set setWildExtendsT = ImmutableSet.of(); private Set setWildExtendsNumber = ImmutableSet.of(); private Set> setWildExtendsComparable = ImmutableSet.of(); private List listWildBuilder1 = ImmutableList.of(); private List listWildBuilder2 = ImmutableList.of(); private Map mapWildBuilder1 = ImmutableMap.of(); private Map mapWildKey = ImmutableMap.of(); private Table table = ImmutableTable.of(); /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmGuava beanToCopy) { this.collection = beanToCopy.getCollection(); this.list = beanToCopy.getList(); this.set = beanToCopy.getSet(); this.sortedSet = beanToCopy.getSortedSet(); this.map = beanToCopy.getMap(); this.sortedMap = beanToCopy.getSortedMap(); this.biMap = beanToCopy.getBiMap(); this.multimap = beanToCopy.getMultimap(); this.listMultimap = beanToCopy.getListMultimap(); this.setMultimap = beanToCopy.getSetMultimap(); this.multiset = beanToCopy.getMultiset(); this.sortedMultiset = beanToCopy.getSortedMultiset(); this.collectionInterface = ImmutableList.copyOf(beanToCopy.getCollectionInterface()); this.listInterface = ImmutableList.copyOf(beanToCopy.getListInterface()); this.setInterface = ImmutableSet.copyOf(beanToCopy.getSetInterface()); this.sortedSetInterface = ImmutableSortedSet.copyOfSorted(beanToCopy.getSortedSetInterface()); this.mapInterface = ImmutableMap.copyOf(beanToCopy.getMapInterface()); this.sortedMapInterface = ImmutableSortedMap.copyOfSorted(beanToCopy.getSortedMapInterface()); this.biMapInterface = ImmutableBiMap.copyOf(beanToCopy.getBiMapInterface()); this.multimapInterface = ImmutableMultimap.copyOf(beanToCopy.getMultimapInterface()); this.listMultimapInterface = ImmutableListMultimap.copyOf(beanToCopy.getListMultimapInterface()); this.setMultimapInterface = ImmutableSetMultimap.copyOf(beanToCopy.getSetMultimapInterface()); this.multisetInterface = ImmutableMultiset.copyOf(beanToCopy.getMultisetInterface()); this.sortedMultisetInterface = ImmutableSortedMultiset.copyOfSorted(beanToCopy.getSortedMultisetInterface()); this.listWildExtendsT = beanToCopy.getListWildExtendsT(); this.listWildExtendsNumber = beanToCopy.getListWildExtendsNumber(); this.listWildExtendsComparable = beanToCopy.getListWildExtendsComparable(); this.setWildExtendsT = beanToCopy.getSetWildExtendsT(); this.setWildExtendsNumber = beanToCopy.getSetWildExtendsNumber(); this.setWildExtendsComparable = beanToCopy.getSetWildExtendsComparable(); this.listWildBuilder1 = beanToCopy.getListWildBuilder1(); this.listWildBuilder2 = beanToCopy.getListWildBuilder2(); this.mapWildBuilder1 = beanToCopy.getMapWildBuilder1(); this.mapWildKey = beanToCopy.getMapWildKey(); this.table = beanToCopy.getTable(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1741312354: // collection return this.collection; case 3322014: // list return this.list; case 113762: // set return this.set; case -6890395: // sortedSet return this.sortedSet; case 107868: // map return this.map; case -6896289: // sortedMap return this.sortedMap; case 93710229: // biMap return this.biMap; case 653826435: // multimap return this.multimap; case 1737633857: // listMultimap return this.listMultimap; case -1651820539: // setMultimap return this.setMultimap; case 653832329: // multiset return this.multiset; case 1018567270: // sortedMultiset return this.sortedMultiset; case 420048955: // collectionInterface return this.collectionInterface; case -259084741: // listInterface return this.listInterface; case 2042011383: // setInterface return this.setInterface; case 1019335252: // sortedSetInterface return this.sortedSetInterface; case 651439933: // mapInterface return this.mapInterface; case -371236198: // sortedMapInterface return this.sortedMapInterface; case 2068077860: // biMapInterface return this.biMapInterface; case -1415579914: // multimapInterface return this.multimapInterface; case 1576080888: // listMultimapInterface return this.listMultimapInterface; case -630551884: // setMultimapInterface return this.setMultimapInterface; case -25008464: // multisetInterface return this.multisetInterface; case 271697267: // sortedMultisetInterface return this.sortedMultisetInterface; case -826400637: // listWildExtendsT return this.listWildExtendsT; case 789015706: // listWildExtendsNumber return this.listWildExtendsNumber; case 857377195: // listWildExtendsComparable return this.listWildExtendsComparable; case -844782009: // setWildExtendsT return this.setWildExtendsT; case -1417617066: // setWildExtendsNumber return this.setWildExtendsNumber; case 940785767: // setWildExtendsComparable return this.setWildExtendsComparable; case -436161122: // listWildBuilder1 return this.listWildBuilder1; case -436161121: // listWildBuilder2 return this.listWildBuilder2; case -2009039524: // mapWildBuilder1 return this.mapWildBuilder1; case 1463967033: // mapWildKey return this.mapWildKey; case 110115790: // table return this.table; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1741312354: // collection this.collection = (Collection) newValue; break; case 3322014: // list this.list = (List) newValue; break; case 113762: // set this.set = (Set) newValue; break; case -6890395: // sortedSet this.sortedSet = (SortedSet) newValue; break; case 107868: // map this.map = (Map) newValue; break; case -6896289: // sortedMap this.sortedMap = (SortedMap) newValue; break; case 93710229: // biMap this.biMap = (BiMap) newValue; break; case 653826435: // multimap this.multimap = (Multimap) newValue; break; case 1737633857: // listMultimap this.listMultimap = (ListMultimap) newValue; break; case -1651820539: // setMultimap this.setMultimap = (SetMultimap) newValue; break; case 653832329: // multiset this.multiset = (Multiset) newValue; break; case 1018567270: // sortedMultiset this.sortedMultiset = (SortedMultiset) newValue; break; case 420048955: // collectionInterface this.collectionInterface = (Collection) newValue; break; case -259084741: // listInterface this.listInterface = (List) newValue; break; case 2042011383: // setInterface this.setInterface = (Set) newValue; break; case 1019335252: // sortedSetInterface this.sortedSetInterface = (SortedSet) newValue; break; case 651439933: // mapInterface this.mapInterface = (Map) newValue; break; case -371236198: // sortedMapInterface this.sortedMapInterface = (SortedMap) newValue; break; case 2068077860: // biMapInterface this.biMapInterface = (BiMap) newValue; break; case -1415579914: // multimapInterface this.multimapInterface = (Multimap) newValue; break; case 1576080888: // listMultimapInterface this.listMultimapInterface = (ListMultimap) newValue; break; case -630551884: // setMultimapInterface this.setMultimapInterface = (SetMultimap) newValue; break; case -25008464: // multisetInterface this.multisetInterface = (Multiset) newValue; break; case 271697267: // sortedMultisetInterface this.sortedMultisetInterface = (SortedMultiset) newValue; break; case -826400637: // listWildExtendsT this.listWildExtendsT = (List) newValue; break; case 789015706: // listWildExtendsNumber this.listWildExtendsNumber = (List) newValue; break; case 857377195: // listWildExtendsComparable this.listWildExtendsComparable = (List>) newValue; break; case -844782009: // setWildExtendsT this.setWildExtendsT = (Set) newValue; break; case -1417617066: // setWildExtendsNumber this.setWildExtendsNumber = (Set) newValue; break; case 940785767: // setWildExtendsComparable this.setWildExtendsComparable = (Set>) newValue; break; case -436161122: // listWildBuilder1 this.listWildBuilder1 = (List) newValue; break; case -436161121: // listWildBuilder2 this.listWildBuilder2 = (List) newValue; break; case -2009039524: // mapWildBuilder1 this.mapWildBuilder1 = (Map) newValue; break; case 1463967033: // mapWildKey this.mapWildKey = (Map) newValue; break; case 110115790: // table this.table = (Table) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmGuava build() { return new ImmGuava<>( collection, list, set, sortedSet, map, sortedMap, biMap, multimap, listMultimap, setMultimap, multiset, sortedMultiset, collectionInterface, listInterface, setInterface, sortedSetInterface, mapInterface, sortedMapInterface, biMapInterface, multimapInterface, listMultimapInterface, setMultimapInterface, multisetInterface, sortedMultisetInterface, listWildExtendsT, listWildExtendsNumber, listWildExtendsComparable, setWildExtendsT, setWildExtendsNumber, setWildExtendsComparable, listWildBuilder1, listWildBuilder2, mapWildBuilder1, mapWildKey, table); } //----------------------------------------------------------------------- /** * Sets the collection. * @param collection the new value, not null * @return this, for chaining, not null */ public Builder collection(Collection collection) { JodaBeanUtils.notNull(collection, "collection"); this.collection = collection; return this; } /** * Sets the {@code collection} property in the builder * from an array of objects. * @param collection the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder collection(T... collection) { return collection(ImmutableList.copyOf(collection)); } /** * Sets the list. * @param list the new value, not null * @return this, for chaining, not null */ public Builder list(List list) { JodaBeanUtils.notNull(list, "list"); this.list = list; return this; } /** * Sets the {@code list} property in the builder * from an array of objects. * @param list the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder list(T... list) { return list(ImmutableList.copyOf(list)); } /** * Sets the set. * @param set the new value, not null * @return this, for chaining, not null */ public Builder set(Set set) { JodaBeanUtils.notNull(set, "set"); this.set = set; return this; } /** * Sets the {@code set} property in the builder * from an array of objects. * @param set the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder set(T... set) { return set(ImmutableSet.copyOf(set)); } /** * Sets the sortedSet. * @param sortedSet the new value, not null * @return this, for chaining, not null */ public Builder sortedSet(SortedSet sortedSet) { JodaBeanUtils.notNull(sortedSet, "sortedSet"); this.sortedSet = sortedSet; return this; } /** * Sets the {@code sortedSet} property in the builder * from an array of objects. * @param sortedSet the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder sortedSet(T... sortedSet) { return sortedSet(ImmutableSortedSet.copyOf(sortedSet)); } /** * Sets the map. * @param map the new value, not null * @return this, for chaining, not null */ public Builder map(Map map) { JodaBeanUtils.notNull(map, "map"); this.map = map; return this; } /** * Sets the sortedMap. * @param sortedMap the new value, not null * @return this, for chaining, not null */ public Builder sortedMap(SortedMap sortedMap) { JodaBeanUtils.notNull(sortedMap, "sortedMap"); this.sortedMap = sortedMap; return this; } /** * Sets the biMap. * @param biMap the new value, not null * @return this, for chaining, not null */ public Builder biMap(BiMap biMap) { JodaBeanUtils.notNull(biMap, "biMap"); this.biMap = biMap; return this; } /** * Sets the multimap. * @param multimap the new value, not null * @return this, for chaining, not null */ public Builder multimap(Multimap multimap) { JodaBeanUtils.notNull(multimap, "multimap"); this.multimap = multimap; return this; } /** * Sets the listMultimap. * @param listMultimap the new value, not null * @return this, for chaining, not null */ public Builder listMultimap(ListMultimap listMultimap) { JodaBeanUtils.notNull(listMultimap, "listMultimap"); this.listMultimap = listMultimap; return this; } /** * Sets the setMultimap. * @param setMultimap the new value, not null * @return this, for chaining, not null */ public Builder setMultimap(SetMultimap setMultimap) { JodaBeanUtils.notNull(setMultimap, "setMultimap"); this.setMultimap = setMultimap; return this; } /** * Sets the multiset. * @param multiset the new value, not null * @return this, for chaining, not null */ public Builder multiset(Multiset multiset) { JodaBeanUtils.notNull(multiset, "multiset"); this.multiset = multiset; return this; } /** * Sets the sortedMultiset. * @param sortedMultiset the new value, not null * @return this, for chaining, not null */ public Builder sortedMultiset(SortedMultiset sortedMultiset) { JodaBeanUtils.notNull(sortedMultiset, "sortedMultiset"); this.sortedMultiset = sortedMultiset; return this; } /** * Sets the collectionInterface. * @param collectionInterface the new value, not null * @return this, for chaining, not null */ public Builder collectionInterface(Collection collectionInterface) { JodaBeanUtils.notNull(collectionInterface, "collectionInterface"); this.collectionInterface = collectionInterface; return this; } /** * Sets the {@code collectionInterface} property in the builder * from an array of objects. * @param collectionInterface the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder collectionInterface(T... collectionInterface) { return collectionInterface(ImmutableList.copyOf(collectionInterface)); } /** * Sets the listInterface. * @param listInterface the new value, not null * @return this, for chaining, not null */ public Builder listInterface(List listInterface) { JodaBeanUtils.notNull(listInterface, "listInterface"); this.listInterface = listInterface; return this; } /** * Sets the {@code listInterface} property in the builder * from an array of objects. * @param listInterface the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder listInterface(T... listInterface) { return listInterface(ImmutableList.copyOf(listInterface)); } /** * Sets the setInterface. * @param setInterface the new value, not null * @return this, for chaining, not null */ public Builder setInterface(Set setInterface) { JodaBeanUtils.notNull(setInterface, "setInterface"); this.setInterface = setInterface; return this; } /** * Sets the {@code setInterface} property in the builder * from an array of objects. * @param setInterface the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder setInterface(T... setInterface) { return setInterface(ImmutableSet.copyOf(setInterface)); } /** * Sets the sortedSetInterface. * @param sortedSetInterface the new value, not null * @return this, for chaining, not null */ public Builder sortedSetInterface(SortedSet sortedSetInterface) { JodaBeanUtils.notNull(sortedSetInterface, "sortedSetInterface"); this.sortedSetInterface = sortedSetInterface; return this; } /** * Sets the {@code sortedSetInterface} property in the builder * from an array of objects. * @param sortedSetInterface the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder sortedSetInterface(T... sortedSetInterface) { return sortedSetInterface(ImmutableSortedSet.copyOf(sortedSetInterface)); } /** * Sets the mapInterface. * @param mapInterface the new value, not null * @return this, for chaining, not null */ public Builder mapInterface(Map mapInterface) { JodaBeanUtils.notNull(mapInterface, "mapInterface"); this.mapInterface = mapInterface; return this; } /** * Sets the sortedMapInterface. * @param sortedMapInterface the new value, not null * @return this, for chaining, not null */ public Builder sortedMapInterface(SortedMap sortedMapInterface) { JodaBeanUtils.notNull(sortedMapInterface, "sortedMapInterface"); this.sortedMapInterface = sortedMapInterface; return this; } /** * Sets the biMapInterface. * @param biMapInterface the new value, not null * @return this, for chaining, not null */ public Builder biMapInterface(BiMap biMapInterface) { JodaBeanUtils.notNull(biMapInterface, "biMapInterface"); this.biMapInterface = biMapInterface; return this; } /** * Sets the multimapInterface. * @param multimapInterface the new value, not null * @return this, for chaining, not null */ public Builder multimapInterface(Multimap multimapInterface) { JodaBeanUtils.notNull(multimapInterface, "multimapInterface"); this.multimapInterface = multimapInterface; return this; } /** * Sets the listMultimapInterface. * @param listMultimapInterface the new value, not null * @return this, for chaining, not null */ public Builder listMultimapInterface(ListMultimap listMultimapInterface) { JodaBeanUtils.notNull(listMultimapInterface, "listMultimapInterface"); this.listMultimapInterface = listMultimapInterface; return this; } /** * Sets the setMultimapInterface. * @param setMultimapInterface the new value, not null * @return this, for chaining, not null */ public Builder setMultimapInterface(SetMultimap setMultimapInterface) { JodaBeanUtils.notNull(setMultimapInterface, "setMultimapInterface"); this.setMultimapInterface = setMultimapInterface; return this; } /** * Sets the multisetInterface. * @param multisetInterface the new value, not null * @return this, for chaining, not null */ public Builder multisetInterface(Multiset multisetInterface) { JodaBeanUtils.notNull(multisetInterface, "multisetInterface"); this.multisetInterface = multisetInterface; return this; } /** * Sets the sortedMultisetInterface. * @param sortedMultisetInterface the new value, not null * @return this, for chaining, not null */ public Builder sortedMultisetInterface(SortedMultiset sortedMultisetInterface) { JodaBeanUtils.notNull(sortedMultisetInterface, "sortedMultisetInterface"); this.sortedMultisetInterface = sortedMultisetInterface; return this; } /** * Sets the listWildExtendsT. * @param listWildExtendsT the new value, not null * @return this, for chaining, not null */ public Builder listWildExtendsT(List listWildExtendsT) { JodaBeanUtils.notNull(listWildExtendsT, "listWildExtendsT"); this.listWildExtendsT = listWildExtendsT; return this; } /** * Sets the {@code listWildExtendsT} property in the builder * from an array of objects. * @param listWildExtendsT the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder listWildExtendsT(T... listWildExtendsT) { return listWildExtendsT(ImmutableList.copyOf(listWildExtendsT)); } /** * Sets the listWildExtendsNumber. * @param listWildExtendsNumber the new value, not null * @return this, for chaining, not null */ public Builder listWildExtendsNumber(List listWildExtendsNumber) { JodaBeanUtils.notNull(listWildExtendsNumber, "listWildExtendsNumber"); this.listWildExtendsNumber = listWildExtendsNumber; return this; } /** * Sets the {@code listWildExtendsNumber} property in the builder * from an array of objects. * @param listWildExtendsNumber the new value, not null * @return this, for chaining, not null */ public Builder listWildExtendsNumber(Number... listWildExtendsNumber) { return listWildExtendsNumber(ImmutableList.copyOf(listWildExtendsNumber)); } /** * Sets the listWildExtendsComparable. * @param listWildExtendsComparable the new value, not null * @return this, for chaining, not null */ public Builder listWildExtendsComparable(List> listWildExtendsComparable) { JodaBeanUtils.notNull(listWildExtendsComparable, "listWildExtendsComparable"); this.listWildExtendsComparable = listWildExtendsComparable; return this; } /** * Sets the {@code listWildExtendsComparable} property in the builder * from an array of objects. * @param listWildExtendsComparable the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder listWildExtendsComparable(Comparable... listWildExtendsComparable) { return listWildExtendsComparable(ImmutableList.copyOf(listWildExtendsComparable)); } /** * Sets the setWildExtendsT. * @param setWildExtendsT the new value, not null * @return this, for chaining, not null */ public Builder setWildExtendsT(Set setWildExtendsT) { JodaBeanUtils.notNull(setWildExtendsT, "setWildExtendsT"); this.setWildExtendsT = setWildExtendsT; return this; } /** * Sets the {@code setWildExtendsT} property in the builder * from an array of objects. * @param setWildExtendsT the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder setWildExtendsT(T... setWildExtendsT) { return setWildExtendsT(ImmutableSet.copyOf(setWildExtendsT)); } /** * Sets the setWildExtendsNumber. * @param setWildExtendsNumber the new value, not null * @return this, for chaining, not null */ public Builder setWildExtendsNumber(Set setWildExtendsNumber) { JodaBeanUtils.notNull(setWildExtendsNumber, "setWildExtendsNumber"); this.setWildExtendsNumber = setWildExtendsNumber; return this; } /** * Sets the {@code setWildExtendsNumber} property in the builder * from an array of objects. * @param setWildExtendsNumber the new value, not null * @return this, for chaining, not null */ public Builder setWildExtendsNumber(Number... setWildExtendsNumber) { return setWildExtendsNumber(ImmutableSet.copyOf(setWildExtendsNumber)); } /** * Sets the setWildExtendsComparable. * @param setWildExtendsComparable the new value, not null * @return this, for chaining, not null */ public Builder setWildExtendsComparable(Set> setWildExtendsComparable) { JodaBeanUtils.notNull(setWildExtendsComparable, "setWildExtendsComparable"); this.setWildExtendsComparable = setWildExtendsComparable; return this; } /** * Sets the {@code setWildExtendsComparable} property in the builder * from an array of objects. * @param setWildExtendsComparable the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder setWildExtendsComparable(Comparable... setWildExtendsComparable) { return setWildExtendsComparable(ImmutableSet.copyOf(setWildExtendsComparable)); } /** * Sets the listWildBuilder1. * @param listWildBuilder1 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder1(List listWildBuilder1) { JodaBeanUtils.notNull(listWildBuilder1, "listWildBuilder1"); this.listWildBuilder1 = listWildBuilder1; return this; } /** * Sets the {@code listWildBuilder1} property in the builder * from an array of objects. * @param listWildBuilder1 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder1(Object... listWildBuilder1) { return listWildBuilder1(ImmutableList.copyOf(listWildBuilder1)); } /** * Sets the listWildBuilder2. * @param listWildBuilder2 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder2(List listWildBuilder2) { JodaBeanUtils.notNull(listWildBuilder2, "listWildBuilder2"); this.listWildBuilder2 = listWildBuilder2; return this; } /** * Sets the {@code listWildBuilder2} property in the builder * from an array of objects. * @param listWildBuilder2 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder2(Address... listWildBuilder2) { return listWildBuilder2(ImmutableList.copyOf(listWildBuilder2)); } /** * Sets the mapWildBuilder1. * @param mapWildBuilder1 the new value, not null * @return this, for chaining, not null */ public Builder mapWildBuilder1(Map mapWildBuilder1) { JodaBeanUtils.notNull(mapWildBuilder1, "mapWildBuilder1"); this.mapWildBuilder1 = mapWildBuilder1; return this; } /** * Sets the mapWildKey. * @param mapWildKey the new value, not null * @return this, for chaining, not null */ public Builder mapWildKey(Map mapWildKey) { JodaBeanUtils.notNull(mapWildKey, "mapWildKey"); this.mapWildKey = mapWildKey; return this; } /** * Sets the table. * @param table the new value, not null * @return this, for chaining, not null */ public Builder table(Table table) { JodaBeanUtils.notNull(table, "table"); this.table = table; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(1152); buf.append("ImmGuava.Builder{"); buf.append("collection").append('=').append(JodaBeanUtils.toString(collection)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("set").append('=').append(JodaBeanUtils.toString(set)).append(',').append(' '); buf.append("sortedSet").append('=').append(JodaBeanUtils.toString(sortedSet)).append(',').append(' '); buf.append("map").append('=').append(JodaBeanUtils.toString(map)).append(',').append(' '); buf.append("sortedMap").append('=').append(JodaBeanUtils.toString(sortedMap)).append(',').append(' '); buf.append("biMap").append('=').append(JodaBeanUtils.toString(biMap)).append(',').append(' '); buf.append("multimap").append('=').append(JodaBeanUtils.toString(multimap)).append(',').append(' '); buf.append("listMultimap").append('=').append(JodaBeanUtils.toString(listMultimap)).append(',').append(' '); buf.append("setMultimap").append('=').append(JodaBeanUtils.toString(setMultimap)).append(',').append(' '); buf.append("multiset").append('=').append(JodaBeanUtils.toString(multiset)).append(',').append(' '); buf.append("sortedMultiset").append('=').append(JodaBeanUtils.toString(sortedMultiset)).append(',').append(' '); buf.append("collectionInterface").append('=').append(JodaBeanUtils.toString(collectionInterface)).append(',').append(' '); buf.append("listInterface").append('=').append(JodaBeanUtils.toString(listInterface)).append(',').append(' '); buf.append("setInterface").append('=').append(JodaBeanUtils.toString(setInterface)).append(',').append(' '); buf.append("sortedSetInterface").append('=').append(JodaBeanUtils.toString(sortedSetInterface)).append(',').append(' '); buf.append("mapInterface").append('=').append(JodaBeanUtils.toString(mapInterface)).append(',').append(' '); buf.append("sortedMapInterface").append('=').append(JodaBeanUtils.toString(sortedMapInterface)).append(',').append(' '); buf.append("biMapInterface").append('=').append(JodaBeanUtils.toString(biMapInterface)).append(',').append(' '); buf.append("multimapInterface").append('=').append(JodaBeanUtils.toString(multimapInterface)).append(',').append(' '); buf.append("listMultimapInterface").append('=').append(JodaBeanUtils.toString(listMultimapInterface)).append(',').append(' '); buf.append("setMultimapInterface").append('=').append(JodaBeanUtils.toString(setMultimapInterface)).append(',').append(' '); buf.append("multisetInterface").append('=').append(JodaBeanUtils.toString(multisetInterface)).append(',').append(' '); buf.append("sortedMultisetInterface").append('=').append(JodaBeanUtils.toString(sortedMultisetInterface)).append(',').append(' '); buf.append("listWildExtendsT").append('=').append(JodaBeanUtils.toString(listWildExtendsT)).append(',').append(' '); buf.append("listWildExtendsNumber").append('=').append(JodaBeanUtils.toString(listWildExtendsNumber)).append(',').append(' '); buf.append("listWildExtendsComparable").append('=').append(JodaBeanUtils.toString(listWildExtendsComparable)).append(',').append(' '); buf.append("setWildExtendsT").append('=').append(JodaBeanUtils.toString(setWildExtendsT)).append(',').append(' '); buf.append("setWildExtendsNumber").append('=').append(JodaBeanUtils.toString(setWildExtendsNumber)).append(',').append(' '); buf.append("setWildExtendsComparable").append('=').append(JodaBeanUtils.toString(setWildExtendsComparable)).append(',').append(' '); buf.append("listWildBuilder1").append('=').append(JodaBeanUtils.toString(listWildBuilder1)).append(',').append(' '); buf.append("listWildBuilder2").append('=').append(JodaBeanUtils.toString(listWildBuilder2)).append(',').append(' '); buf.append("mapWildBuilder1").append('=').append(JodaBeanUtils.toString(mapWildBuilder1)).append(',').append(' '); buf.append("mapWildKey").append('=').append(JodaBeanUtils.toString(mapWildKey)).append(',').append(' '); buf.append("table").append('=').append(JodaBeanUtils.toString(table)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmJodaConvertBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.convert.FromString; import org.joda.convert.ToString; /** * An immutable bean that is also a Joda-Convert type, used for testing. */ @BeanDefinition public final class ImmJodaConvertBean implements ImmutableBean { /** * The base value. */ @PropertyDefinition private final String base; /** * The extra value. */ @PropertyDefinition private final int extra; @FromString public ImmJodaConvertBean(String text) { base = text.substring(0, text.indexOf(':')); extra = Integer.parseInt(text.substring(text.indexOf(':') + 1)); } @ToString public String formattedString() { return base + ":" + extra; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmJodaConvertBean}. * @return the meta-bean, not null */ public static ImmJodaConvertBean.Meta meta() { return ImmJodaConvertBean.Meta.INSTANCE; } static { MetaBean.register(ImmJodaConvertBean.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmJodaConvertBean.Builder builder() { return new ImmJodaConvertBean.Builder(); } private ImmJodaConvertBean( String base, int extra) { this.base = base; this.extra = extra; } @Override public ImmJodaConvertBean.Meta metaBean() { return ImmJodaConvertBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the base value. * @return the value of the property */ public String getBase() { return base; } //----------------------------------------------------------------------- /** * Gets the extra value. * @return the value of the property */ public int getExtra() { return extra; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmJodaConvertBean other = (ImmJodaConvertBean) obj; return JodaBeanUtils.equal(this.base, other.base) && (this.extra == other.extra); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(base); hash = hash * 31 + JodaBeanUtils.hashCode(extra); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmJodaConvertBean{"); buf.append("base").append('=').append(JodaBeanUtils.toString(base)).append(',').append(' '); buf.append("extra").append('=').append(JodaBeanUtils.toString(extra)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmJodaConvertBean}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code base} property. */ private final MetaProperty base = DirectMetaProperty.ofImmutable( this, "base", ImmJodaConvertBean.class, String.class); /** * The meta-property for the {@code extra} property. */ private final MetaProperty extra = DirectMetaProperty.ofImmutable( this, "extra", ImmJodaConvertBean.class, Integer.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "base", "extra"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3016401: // base return this.base; case 96965648: // extra return this.extra; } return super.metaPropertyGet(propertyName); } @Override public ImmJodaConvertBean.Builder builder() { return new ImmJodaConvertBean.Builder(); } @Override public Class beanType() { return ImmJodaConvertBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code base} property. * @return the meta-property, not null */ public MetaProperty base() { return base; } /** * The meta-property for the {@code extra} property. * @return the meta-property, not null */ public MetaProperty extra() { return extra; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3016401: // base return ((ImmJodaConvertBean) bean).getBase(); case 96965648: // extra return ((ImmJodaConvertBean) bean).getExtra(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmJodaConvertBean}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String base; private int extra; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmJodaConvertBean beanToCopy) { this.base = beanToCopy.getBase(); this.extra = beanToCopy.getExtra(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3016401: // base return this.base; case 96965648: // extra return this.extra; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3016401: // base this.base = (String) newValue; break; case 96965648: // extra this.extra = (Integer) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmJodaConvertBean build() { return new ImmJodaConvertBean( base, extra); } //----------------------------------------------------------------------- /** * Sets the base value. * @param base the new value * @return this, for chaining, not null */ public Builder base(String base) { this.base = base; return this; } /** * Sets the extra value. * @param extra the new value * @return this, for chaining, not null */ public Builder extra(int extra) { this.extra = extra; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmJodaConvertBean.Builder{"); buf.append("base").append('=').append(JodaBeanUtils.toString(base)).append(',').append(' '); buf.append("extra").append('=').append(JodaBeanUtils.toString(extra)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmJodaConvertWrapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Wraps {@code ImmJodaConvertBean}, used for testing. */ @BeanDefinition(factoryName = "of") public final class ImmJodaConvertWrapper implements ImmutableBean { /** * The base value. */ @PropertyDefinition private final ImmJodaConvertBean bean; /** * The extra value. */ @PropertyDefinition private final String description; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmJodaConvertWrapper}. * @return the meta-bean, not null */ public static ImmJodaConvertWrapper.Meta meta() { return ImmJodaConvertWrapper.Meta.INSTANCE; } static { MetaBean.register(ImmJodaConvertWrapper.Meta.INSTANCE); } /** * Obtains an instance. * @param bean the value of the property * @param description the value of the property * @return the instance */ public static ImmJodaConvertWrapper of( ImmJodaConvertBean bean, String description) { return new ImmJodaConvertWrapper( bean, description); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmJodaConvertWrapper.Builder builder() { return new ImmJodaConvertWrapper.Builder(); } private ImmJodaConvertWrapper( ImmJodaConvertBean bean, String description) { this.bean = bean; this.description = description; } @Override public ImmJodaConvertWrapper.Meta metaBean() { return ImmJodaConvertWrapper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the base value. * @return the value of the property */ public ImmJodaConvertBean getBean() { return bean; } //----------------------------------------------------------------------- /** * Gets the extra value. * @return the value of the property */ public String getDescription() { return description; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmJodaConvertWrapper other = (ImmJodaConvertWrapper) obj; return JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.description, other.description); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(description); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmJodaConvertWrapper{"); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("description").append('=').append(JodaBeanUtils.toString(description)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmJodaConvertWrapper}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code bean} property. */ private final MetaProperty bean = DirectMetaProperty.ofImmutable( this, "bean", ImmJodaConvertWrapper.class, ImmJodaConvertBean.class); /** * The meta-property for the {@code description} property. */ private final MetaProperty description = DirectMetaProperty.ofImmutable( this, "description", ImmJodaConvertWrapper.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "bean", "description"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3019696: // bean return this.bean; case -1724546052: // description return this.description; } return super.metaPropertyGet(propertyName); } @Override public ImmJodaConvertWrapper.Builder builder() { return new ImmJodaConvertWrapper.Builder(); } @Override public Class beanType() { return ImmJodaConvertWrapper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code bean} property. * @return the meta-property, not null */ public MetaProperty bean() { return bean; } /** * The meta-property for the {@code description} property. * @return the meta-property, not null */ public MetaProperty description() { return description; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3019696: // bean return ((ImmJodaConvertWrapper) bean).getBean(); case -1724546052: // description return ((ImmJodaConvertWrapper) bean).getDescription(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmJodaConvertWrapper}. */ public static final class Builder extends DirectFieldsBeanBuilder { private ImmJodaConvertBean bean; private String description; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmJodaConvertWrapper beanToCopy) { this.bean = beanToCopy.getBean(); this.description = beanToCopy.getDescription(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3019696: // bean return this.bean; case -1724546052: // description return this.description; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3019696: // bean this.bean = (ImmJodaConvertBean) newValue; break; case -1724546052: // description this.description = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmJodaConvertWrapper build() { return new ImmJodaConvertWrapper( bean, description); } //----------------------------------------------------------------------- /** * Sets the base value. * @param bean the new value * @return this, for chaining, not null */ public Builder bean(ImmJodaConvertBean bean) { this.bean = bean; return this; } /** * Sets the extra value. * @param description the new value * @return this, for chaining, not null */ public Builder description(String description) { this.description = description; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmJodaConvertWrapper.Builder{"); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("description").append('=').append(JodaBeanUtils.toString(description)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmKey.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.ser.SerDeserializer; /** * Mock key JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "private") public final class ImmKey implements ImmutableBean, IKey, Serializable { /** * The name. * The name is unique in conjunction with the type. */ @PropertyDefinition(validate = "notEmpty", overrideGet = true) private final String name; /** * The deserializer. */ public static final SerDeserializer DESERIALIZER = new ImmKeyDeserializer(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmKey}. * @return the meta-bean, not null */ public static ImmKey.Meta meta() { return ImmKey.Meta.INSTANCE; } static { MetaBean.register(ImmKey.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmKey.Builder builder() { return new ImmKey.Builder(); } private ImmKey( String name) { JodaBeanUtils.notEmpty(name, "name"); this.name = name; } @Override public ImmKey.Meta metaBean() { return ImmKey.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * The name is unique in conjunction with the type. * @return the value of the property, not empty */ @Override public String getName() { return name; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmKey other = (ImmKey) obj; return JodaBeanUtils.equal(this.name, other.name); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(name); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmKey{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmKey}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofImmutable( this, "name", ImmKey.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public ImmKey.Builder builder() { return new ImmKey.Builder(); } @Override public Class beanType() { return ImmKey.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((ImmKey) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmKey}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String name; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmKey beanToCopy) { this.name = beanToCopy.getName(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3373707: // name this.name = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmKey build() { return new ImmKey( name); } //----------------------------------------------------------------------- /** * Sets the name. * The name is unique in conjunction with the type. * @param name the new value, not empty * @return this, for chaining, not null */ public Builder name(String name) { JodaBeanUtils.notEmpty(name, "name"); this.name = name; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmKey.Builder{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmKeyDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.DefaultDeserializer; /** * Mock deserializer. */ final class ImmKeyDeserializer extends DefaultDeserializer { @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { if ("key".equals(propertyName)) { return metaBean.metaProperty("name"); } return super.findMetaProperty(beanType, metaBean, propertyName); } } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmKeyHolder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.ser.SerDeserializer; /** * Mock key JavaBean, used for testing. */ @BeanDefinition public final class ImmKeyHolder implements ImmutableBean, Serializable { @PropertyDefinition(validate = "notNull") private final ImmKey value; /** * The deserializer. */ public static final SerDeserializer DESERIALIZER = new ImmKeyHolderDeserializer(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmKeyHolder}. * @return the meta-bean, not null */ public static ImmKeyHolder.Meta meta() { return ImmKeyHolder.Meta.INSTANCE; } static { MetaBean.register(ImmKeyHolder.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmKeyHolder.Builder builder() { return new ImmKeyHolder.Builder(); } private ImmKeyHolder( ImmKey value) { JodaBeanUtils.notNull(value, "value"); this.value = value; } @Override public ImmKeyHolder.Meta metaBean() { return ImmKeyHolder.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property, not null */ public ImmKey getValue() { return value; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmKeyHolder other = (ImmKeyHolder) obj; return JodaBeanUtils.equal(this.value, other.value); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmKeyHolder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmKeyHolder}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofImmutable( this, "value", ImmKeyHolder.class, ImmKey.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public ImmKeyHolder.Builder builder() { return new ImmKeyHolder.Builder(); } @Override public Class beanType() { return ImmKeyHolder.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmKeyHolder) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmKeyHolder}. */ public static final class Builder extends DirectFieldsBeanBuilder { private ImmKey value; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmKeyHolder beanToCopy) { this.value = beanToCopy.getValue(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (ImmKey) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmKeyHolder build() { return new ImmKeyHolder( value); } //----------------------------------------------------------------------- /** * Sets the value. * @param value the new value, not null * @return this, for chaining, not null */ public Builder value(ImmKey value) { JodaBeanUtils.notNull(value, "value"); this.value = value; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmKeyHolder.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmKeyHolderDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.reflect.Type; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.impl.BufferingBeanBuilder; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.ser.DefaultDeserializer; import com.google.common.reflect.TypeToken; /** * Mock deserializer. */ final class ImmKeyHolderDeserializer extends DefaultDeserializer { @SuppressWarnings("serial") private static final Type VALUE_TYPE = new TypeToken>() { }.getType(); @SuppressWarnings({ "unchecked", "rawtypes" }) private static final StandaloneMetaProperty> VALUE_PROPERTY = StandaloneMetaProperty.of( "value", ImmKeyHolder.meta(), (Class) ImmGeneric.class, VALUE_TYPE); ImmKeyHolderDeserializer() { } @Override public BeanBuilder createBuilder(Class beanType, MetaBean metaBean) { return BufferingBeanBuilder.of(metaBean); } @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { if (propertyName.equals(VALUE_PROPERTY.name())) { return VALUE_PROPERTY; } else { return metaBean.metaProperty(propertyName); } } @Override public void setValue(BeanBuilder builder, MetaProperty metaProp, Object value) { if (metaProp.equals(VALUE_PROPERTY)) { ImmGeneric generic = (ImmGeneric) value; builder.set(ImmKeyHolder.meta().value(), toImmKey(generic)); } else { builder.set(metaProp, value); } } private ImmKey toImmKey(ImmGeneric generic) { return ImmKey.builder() .name(String.valueOf(generic.getValue())) .build(); } } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmKeyList.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; /** * Mock list of keys JavaBean, used for testing. */ @BeanDefinition(constructorScope = "private") public final class ImmKeyList implements ImmutableBean, Serializable { /** * The keys. */ @PropertyDefinition(validate = "notEmpty") private final ImmutableList keys; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmKeyList}. * @return the meta-bean, not null */ public static ImmKeyList.Meta meta() { return ImmKeyList.Meta.INSTANCE; } static { MetaBean.register(ImmKeyList.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmKeyList.Builder builder() { return new ImmKeyList.Builder(); } private ImmKeyList( List keys) { JodaBeanUtils.notEmpty(keys, "keys"); this.keys = ImmutableList.copyOf(keys); } @Override public ImmKeyList.Meta metaBean() { return ImmKeyList.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the keys. * @return the value of the property, not empty */ public ImmutableList getKeys() { return keys; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmKeyList other = (ImmKeyList) obj; return JodaBeanUtils.equal(this.keys, other.keys); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(keys); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmKeyList{"); buf.append("keys").append('=').append(JodaBeanUtils.toString(keys)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmKeyList}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code keys} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> keys = DirectMetaProperty.ofImmutable( this, "keys", ImmKeyList.class, (Class) ImmutableList.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "keys"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3288564: // keys return this.keys; } return super.metaPropertyGet(propertyName); } @Override public ImmKeyList.Builder builder() { return new ImmKeyList.Builder(); } @Override public Class beanType() { return ImmKeyList.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code keys} property. * @return the meta-property, not null */ public MetaProperty> keys() { return keys; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3288564: // keys return ((ImmKeyList) bean).getKeys(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmKeyList}. */ public static final class Builder extends DirectFieldsBeanBuilder { private List keys = ImmutableList.of(); /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmKeyList beanToCopy) { this.keys = beanToCopy.getKeys(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3288564: // keys return this.keys; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3288564: // keys this.keys = (List) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmKeyList build() { return new ImmKeyList( keys); } //----------------------------------------------------------------------- /** * Sets the keys. * @param keys the new value, not empty * @return this, for chaining, not null */ public Builder keys(List keys) { JodaBeanUtils.notEmpty(keys, "keys"); this.keys = keys; return this; } /** * Sets the {@code keys} property in the builder * from an array of objects. * @param keys the new value, not empty * @return this, for chaining, not null */ public Builder keys(IKey... keys) { return keys(ImmutableList.copyOf(keys)); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmKeyList.Builder{"); buf.append("keys").append('=').append(JodaBeanUtils.toString(keys)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmMappedKey.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "private") public final class ImmMappedKey implements ImmutableBean, Serializable { // note each element on a new line /** * The map of data, keyed by an arbitrary key interface. */ @PropertyDefinition(validate = "notNull", builderType = "Map") private final ImmutableMap data; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmMappedKey}. * @return the meta-bean, not null */ public static ImmMappedKey.Meta meta() { return ImmMappedKey.Meta.INSTANCE; } static { MetaBean.register(ImmMappedKey.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmMappedKey.Builder builder() { return new ImmMappedKey.Builder(); } private ImmMappedKey( Map data) { JodaBeanUtils.notNull(data, "data"); this.data = ImmutableMap.copyOf(data); } @Override public ImmMappedKey.Meta metaBean() { return ImmMappedKey.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the map of data, keyed by an arbitrary key interface. * @return the value of the property, not null */ public ImmutableMap getData() { return data; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmMappedKey other = (ImmMappedKey) obj; return JodaBeanUtils.equal(this.data, other.data); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(data); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmMappedKey{"); buf.append("data").append('=').append(JodaBeanUtils.toString(data)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmMappedKey}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code data} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> data = DirectMetaProperty.ofImmutable( this, "data", ImmMappedKey.class, (Class) ImmutableMap.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "data"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3076010: // data return this.data; } return super.metaPropertyGet(propertyName); } @Override public ImmMappedKey.Builder builder() { return new ImmMappedKey.Builder(); } @Override public Class beanType() { return ImmMappedKey.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code data} property. * @return the meta-property, not null */ public MetaProperty> data() { return data; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3076010: // data return ((ImmMappedKey) bean).getData(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmMappedKey}. */ public static final class Builder extends DirectFieldsBeanBuilder { private Map data = ImmutableMap.of(); /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmMappedKey beanToCopy) { this.data = beanToCopy.getData(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3076010: // data return this.data; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3076010: // data this.data = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmMappedKey build() { return new ImmMappedKey( data); } //----------------------------------------------------------------------- /** * Sets the map of data, keyed by an arbitrary key interface. * @param data the new value, not null * @return this, for chaining, not null */ public Builder data(Map data) { JodaBeanUtils.notNull(data, "data"); this.data = data; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmMappedKey.Builder{"); buf.append("data").append('=').append(JodaBeanUtils.toString(data)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmMinimalMetaBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectPrivateBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock address JavaBean, used for testing. *

* Minimal with private scope meta and builder. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal", builderScope = "private", metaScope = "private") public final class ImmMinimalMetaBuilder implements ImmutableBean { /** * The number. */ @PropertyDefinition private final int number; /** * The street. */ @PropertyDefinition(validate = "notNull") private final String street; /** * The city. */ @PropertyDefinition(validate = "notNull") private final String city; /** * The owner. */ @PropertyDefinition(validate = "notNull") private final ImmPerson owner; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmMinimalMetaBuilder}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( ImmMinimalMetaBuilder.class, new String[] { "number", "street", "city", "owner"}, () -> new ImmMinimalMetaBuilder.Builder(), b -> b.getNumber(), b -> b.getStreet(), b -> b.getCity(), b -> b.getOwner()); /** * The meta-bean for {@code ImmMinimalMetaBuilder}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } private ImmMinimalMetaBuilder( int number, String street, String city, ImmPerson owner) { JodaBeanUtils.notNull(street, "street"); JodaBeanUtils.notNull(city, "city"); JodaBeanUtils.notNull(owner, "owner"); this.number = number; this.street = street; this.city = city; this.owner = owner; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the street. * @return the value of the property, not null */ public String getStreet() { return street; } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property, not null */ public ImmPerson getOwner() { return owner; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmMinimalMetaBuilder other = (ImmMinimalMetaBuilder) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.city, other.city) && JodaBeanUtils.equal(this.owner, other.owner); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(city); hash = hash * 31 + JodaBeanUtils.hashCode(owner); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmMinimalMetaBuilder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmMinimalMetaBuilder}. */ private static final class Builder extends DirectPrivateBeanBuilder { private int number; private String street; private String city; private ImmPerson owner; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 106164915: // owner return this.owner; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (Integer) newValue; break; case -891990013: // street this.street = (String) newValue; break; case 3053931: // city this.city = (String) newValue; break; case 106164915: // owner this.owner = (ImmPerson) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public ImmMinimalMetaBuilder build() { return new ImmMinimalMetaBuilder( number, street, city, owner); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmMinimalMetaBuilder.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmMinimalPrivateBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectPrivateBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock address JavaBean, used for testing. *

* Minimal with private scope builder. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal", builderScope = "private") public final class ImmMinimalPrivateBuilder implements ImmutableBean { /** * The number. */ @PropertyDefinition private final int number; /** * The street. */ @PropertyDefinition(validate = "notNull") private final String street; /** * The city. */ @PropertyDefinition(validate = "notNull") private final String city; /** * The owner. */ @PropertyDefinition(validate = "notNull") private final ImmPerson owner; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmMinimalPrivateBuilder}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( ImmMinimalPrivateBuilder.class, new String[] { "number", "street", "city", "owner"}, () -> new ImmMinimalPrivateBuilder.Builder(), b -> b.getNumber(), b -> b.getStreet(), b -> b.getCity(), b -> b.getOwner()); /** * The meta-bean for {@code ImmMinimalPrivateBuilder}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } private ImmMinimalPrivateBuilder( int number, String street, String city, ImmPerson owner) { JodaBeanUtils.notNull(street, "street"); JodaBeanUtils.notNull(city, "city"); JodaBeanUtils.notNull(owner, "owner"); this.number = number; this.street = street; this.city = city; this.owner = owner; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the street. * @return the value of the property, not null */ public String getStreet() { return street; } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property, not null */ public ImmPerson getOwner() { return owner; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmMinimalPrivateBuilder other = (ImmMinimalPrivateBuilder) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.city, other.city) && JodaBeanUtils.equal(this.owner, other.owner); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(city); hash = hash * 31 + JodaBeanUtils.hashCode(owner); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmMinimalPrivateBuilder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmMinimalPrivateBuilder}. */ private static final class Builder extends DirectPrivateBeanBuilder { private int number; private String street; private String city; private ImmPerson owner; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 106164915: // owner return this.owner; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (Integer) newValue; break; case -891990013: // street this.street = (String) newValue; break; case 3053931: // city this.city = (String) newValue; break; case 106164915: // owner this.owner = (ImmPerson) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public ImmMinimalPrivateBuilder build() { return new ImmMinimalPrivateBuilder( number, street, city, owner); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmMinimalPrivateBuilder.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmNamedKey.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock key JavaBean implementing Joda-Convert interface, used for testing. */ @BeanDefinition(constructorScope = "private", factoryName = "of") public final class ImmNamedKey implements ImmutableBean, INamedKey, Serializable { /** * The name. */ @PropertyDefinition(validate = "notEmpty", overrideGet = true) private final String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmNamedKey}. * @return the meta-bean, not null */ public static ImmNamedKey.Meta meta() { return ImmNamedKey.Meta.INSTANCE; } static { MetaBean.register(ImmNamedKey.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Obtains an instance. * @param name the value of the property, not empty * @return the instance */ public static ImmNamedKey of( String name) { return new ImmNamedKey( name); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmNamedKey.Builder builder() { return new ImmNamedKey.Builder(); } private ImmNamedKey( String name) { JodaBeanUtils.notEmpty(name, "name"); this.name = name; } @Override public ImmNamedKey.Meta metaBean() { return ImmNamedKey.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not empty */ @Override public String getName() { return name; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmNamedKey other = (ImmNamedKey) obj; return JodaBeanUtils.equal(this.name, other.name); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(name); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmNamedKey{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmNamedKey}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofImmutable( this, "name", ImmNamedKey.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public ImmNamedKey.Builder builder() { return new ImmNamedKey.Builder(); } @Override public Class beanType() { return ImmNamedKey.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((ImmNamedKey) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmNamedKey}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String name; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmNamedKey beanToCopy) { this.name = beanToCopy.getName(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3373707: // name this.name = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmNamedKey build() { return new ImmNamedKey( name); } //----------------------------------------------------------------------- /** * Sets the name. * @param name the new value, not empty * @return this, for chaining, not null */ public Builder name(String name) { JodaBeanUtils.notEmpty(name, "name"); this.name = name; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmNamedKey.Builder{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmOptional.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.ImmutableDefaults; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.base.Optional; /** * Mock. */ @BeanDefinition(factoryName = "of", metaImplements = "ImmOptionalMeta") public final class ImmOptional implements ImmutableBean { // this works but in serialization they fail for lists/maps @PropertyDefinition(validate = "notNull") private final Optional optString; @PropertyDefinition(validate = "notNull") private final Optional optStringEmpty; // these are the recommended approach, nullable fields, optional getters // remove "Guava" to test Java 8 generation @PropertyDefinition(get = "optionalGuava") private final String optStringGetter; @PropertyDefinition(get = "optionalGuava") private final Long optLongGetter; @PropertyDefinition(get = "optionalGuava") private final Integer optIntGetter; @PropertyDefinition(get = "optionalGuava") private final Double optDoubleGetter; @DerivedProperty public int getTwelve() { return 12; } @ImmutableDefaults private static void applyDefaults(Builder builder) { builder.optString = Optional.absent(); builder.optStringEmpty = Optional.absent(); } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmOptional}. * @return the meta-bean, not null */ public static ImmOptional.Meta meta() { return ImmOptional.Meta.INSTANCE; } static { MetaBean.register(ImmOptional.Meta.INSTANCE); } /** * Obtains an instance. * @param optString the value of the property, not null * @param optStringEmpty the value of the property, not null * @param optStringGetter the value of the property * @param optLongGetter the value of the property * @param optIntGetter the value of the property * @param optDoubleGetter the value of the property * @return the instance */ public static ImmOptional of( Optional optString, Optional optStringEmpty, String optStringGetter, Long optLongGetter, Integer optIntGetter, Double optDoubleGetter) { return new ImmOptional( optString, optStringEmpty, optStringGetter, optLongGetter, optIntGetter, optDoubleGetter); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmOptional.Builder builder() { return new ImmOptional.Builder(); } private ImmOptional( Optional optString, Optional optStringEmpty, String optStringGetter, Long optLongGetter, Integer optIntGetter, Double optDoubleGetter) { JodaBeanUtils.notNull(optString, "optString"); JodaBeanUtils.notNull(optStringEmpty, "optStringEmpty"); this.optString = optString; this.optStringEmpty = optStringEmpty; this.optStringGetter = optStringGetter; this.optLongGetter = optLongGetter; this.optIntGetter = optIntGetter; this.optDoubleGetter = optDoubleGetter; } @Override public ImmOptional.Meta metaBean() { return ImmOptional.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the optString. * @return the value of the property, not null */ public Optional getOptString() { return optString; } //----------------------------------------------------------------------- /** * Gets the optStringEmpty. * @return the value of the property, not null */ public Optional getOptStringEmpty() { return optStringEmpty; } //----------------------------------------------------------------------- /** * Gets the optStringGetter. * @return the optional value of the property, not null */ public Optional getOptStringGetter() { return Optional.fromNullable(optStringGetter); } //----------------------------------------------------------------------- /** * Gets the optLongGetter. * @return the optional value of the property, not null */ public Optional getOptLongGetter() { return Optional.fromNullable(optLongGetter); } //----------------------------------------------------------------------- /** * Gets the optIntGetter. * @return the optional value of the property, not null */ public Optional getOptIntGetter() { return Optional.fromNullable(optIntGetter); } //----------------------------------------------------------------------- /** * Gets the optDoubleGetter. * @return the optional value of the property, not null */ public Optional getOptDoubleGetter() { return Optional.fromNullable(optDoubleGetter); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmOptional other = (ImmOptional) obj; return JodaBeanUtils.equal(this.optString, other.optString) && JodaBeanUtils.equal(this.optStringEmpty, other.optStringEmpty) && JodaBeanUtils.equal(this.optStringGetter, other.optStringGetter) && JodaBeanUtils.equal(this.optLongGetter, other.optLongGetter) && JodaBeanUtils.equal(this.optIntGetter, other.optIntGetter) && JodaBeanUtils.equal(this.optDoubleGetter, other.optDoubleGetter); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(optString); hash = hash * 31 + JodaBeanUtils.hashCode(optStringEmpty); hash = hash * 31 + JodaBeanUtils.hashCode(optStringGetter); hash = hash * 31 + JodaBeanUtils.hashCode(optLongGetter); hash = hash * 31 + JodaBeanUtils.hashCode(optIntGetter); hash = hash * 31 + JodaBeanUtils.hashCode(optDoubleGetter); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("ImmOptional{"); buf.append("optString").append('=').append(JodaBeanUtils.toString(optString)).append(',').append(' '); buf.append("optStringEmpty").append('=').append(JodaBeanUtils.toString(optStringEmpty)).append(',').append(' '); buf.append("optStringGetter").append('=').append(JodaBeanUtils.toString(optStringGetter)).append(',').append(' '); buf.append("optLongGetter").append('=').append(JodaBeanUtils.toString(optLongGetter)).append(',').append(' '); buf.append("optIntGetter").append('=').append(JodaBeanUtils.toString(optIntGetter)).append(',').append(' '); buf.append("optDoubleGetter").append('=').append(JodaBeanUtils.toString(optDoubleGetter)).append(',').append(' '); buf.append("twelve").append('=').append(JodaBeanUtils.toString(getTwelve())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmOptional}. */ public static final class Meta extends DirectMetaBean implements ImmOptionalMeta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code optString} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> optString = DirectMetaProperty.ofImmutable( this, "optString", ImmOptional.class, (Class) Optional.class); /** * The meta-property for the {@code optStringEmpty} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> optStringEmpty = DirectMetaProperty.ofImmutable( this, "optStringEmpty", ImmOptional.class, (Class) Optional.class); /** * The meta-property for the {@code optStringGetter} property. */ private final MetaProperty optStringGetter = DirectMetaProperty.ofImmutable( this, "optStringGetter", ImmOptional.class, String.class); /** * The meta-property for the {@code optLongGetter} property. */ private final MetaProperty optLongGetter = DirectMetaProperty.ofImmutable( this, "optLongGetter", ImmOptional.class, Long.class); /** * The meta-property for the {@code optIntGetter} property. */ private final MetaProperty optIntGetter = DirectMetaProperty.ofImmutable( this, "optIntGetter", ImmOptional.class, Integer.class); /** * The meta-property for the {@code optDoubleGetter} property. */ private final MetaProperty optDoubleGetter = DirectMetaProperty.ofImmutable( this, "optDoubleGetter", ImmOptional.class, Double.class); /** * The meta-property for the {@code twelve} property. */ private final MetaProperty twelve = DirectMetaProperty.ofDerived( this, "twelve", ImmOptional.class, Integer.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "optString", "optStringEmpty", "optStringGetter", "optLongGetter", "optIntGetter", "optDoubleGetter", "twelve"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1220339876: // optString return this.optString; case -856788215: // optStringEmpty return this.optStringEmpty; case -740642097: // optStringGetter return this.optStringGetter; case 2046023098: // optLongGetter return this.optLongGetter; case -1931360153: // optIntGetter return this.optIntGetter; case 224984719: // optDoubleGetter return this.optDoubleGetter; case -860970343: // twelve return this.twelve; } return super.metaPropertyGet(propertyName); } @Override public ImmOptional.Builder builder() { return new ImmOptional.Builder(); } @Override public Class beanType() { return ImmOptional.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code optString} property. * @return the meta-property, not null */ public MetaProperty> optString() { return optString; } /** * The meta-property for the {@code optStringEmpty} property. * @return the meta-property, not null */ public MetaProperty> optStringEmpty() { return optStringEmpty; } /** * The meta-property for the {@code optStringGetter} property. * @return the meta-property, not null */ public MetaProperty optStringGetter() { return optStringGetter; } /** * The meta-property for the {@code optLongGetter} property. * @return the meta-property, not null */ public MetaProperty optLongGetter() { return optLongGetter; } /** * The meta-property for the {@code optIntGetter} property. * @return the meta-property, not null */ public MetaProperty optIntGetter() { return optIntGetter; } /** * The meta-property for the {@code optDoubleGetter} property. * @return the meta-property, not null */ public MetaProperty optDoubleGetter() { return optDoubleGetter; } /** * The meta-property for the {@code twelve} property. * @return the meta-property, not null */ public MetaProperty twelve() { return twelve; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1220339876: // optString return ((ImmOptional) bean).getOptString(); case -856788215: // optStringEmpty return ((ImmOptional) bean).getOptStringEmpty(); case -740642097: // optStringGetter return ((ImmOptional) bean).optStringGetter; case 2046023098: // optLongGetter return ((ImmOptional) bean).optLongGetter; case -1931360153: // optIntGetter return ((ImmOptional) bean).optIntGetter; case 224984719: // optDoubleGetter return ((ImmOptional) bean).optDoubleGetter; case -860970343: // twelve return ((ImmOptional) bean).getTwelve(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmOptional}. */ public static final class Builder extends DirectFieldsBeanBuilder { private Optional optString; private Optional optStringEmpty; private String optStringGetter; private Long optLongGetter; private Integer optIntGetter; private Double optDoubleGetter; /** * Restricted constructor. */ private Builder() { applyDefaults(this); } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmOptional beanToCopy) { this.optString = beanToCopy.getOptString(); this.optStringEmpty = beanToCopy.getOptStringEmpty(); this.optStringGetter = beanToCopy.optStringGetter; this.optLongGetter = beanToCopy.optLongGetter; this.optIntGetter = beanToCopy.optIntGetter; this.optDoubleGetter = beanToCopy.optDoubleGetter; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 1220339876: // optString return this.optString; case -856788215: // optStringEmpty return this.optStringEmpty; case -740642097: // optStringGetter return this.optStringGetter; case 2046023098: // optLongGetter return this.optLongGetter; case -1931360153: // optIntGetter return this.optIntGetter; case 224984719: // optDoubleGetter return this.optDoubleGetter; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 1220339876: // optString this.optString = (Optional) newValue; break; case -856788215: // optStringEmpty this.optStringEmpty = (Optional) newValue; break; case -740642097: // optStringGetter this.optStringGetter = (String) newValue; break; case 2046023098: // optLongGetter this.optLongGetter = (Long) newValue; break; case -1931360153: // optIntGetter this.optIntGetter = (Integer) newValue; break; case 224984719: // optDoubleGetter this.optDoubleGetter = (Double) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmOptional build() { return new ImmOptional( optString, optStringEmpty, optStringGetter, optLongGetter, optIntGetter, optDoubleGetter); } //----------------------------------------------------------------------- /** * Sets the optString. * @param optString the new value, not null * @return this, for chaining, not null */ public Builder optString(Optional optString) { JodaBeanUtils.notNull(optString, "optString"); this.optString = optString; return this; } /** * Sets the optStringEmpty. * @param optStringEmpty the new value, not null * @return this, for chaining, not null */ public Builder optStringEmpty(Optional optStringEmpty) { JodaBeanUtils.notNull(optStringEmpty, "optStringEmpty"); this.optStringEmpty = optStringEmpty; return this; } /** * Sets the optStringGetter. * @param optStringGetter the new value * @return this, for chaining, not null */ public Builder optStringGetter(String optStringGetter) { this.optStringGetter = optStringGetter; return this; } /** * Sets the optLongGetter. * @param optLongGetter the new value * @return this, for chaining, not null */ public Builder optLongGetter(Long optLongGetter) { this.optLongGetter = optLongGetter; return this; } /** * Sets the optIntGetter. * @param optIntGetter the new value * @return this, for chaining, not null */ public Builder optIntGetter(Integer optIntGetter) { this.optIntGetter = optIntGetter; return this; } /** * Sets the optDoubleGetter. * @param optDoubleGetter the new value * @return this, for chaining, not null */ public Builder optDoubleGetter(Double optDoubleGetter) { this.optDoubleGetter = optDoubleGetter; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("ImmOptional.Builder{"); buf.append("optString").append('=').append(JodaBeanUtils.toString(optString)).append(',').append(' '); buf.append("optStringEmpty").append('=').append(JodaBeanUtils.toString(optStringEmpty)).append(',').append(' '); buf.append("optStringGetter").append('=').append(JodaBeanUtils.toString(optStringGetter)).append(',').append(' '); buf.append("optLongGetter").append('=').append(JodaBeanUtils.toString(optLongGetter)).append(',').append(' '); buf.append("optIntGetter").append('=').append(JodaBeanUtils.toString(optIntGetter)).append(',').append(' '); buf.append("optDoubleGetter").append('=').append(JodaBeanUtils.toString(optDoubleGetter)).append(',').append(' '); buf.append("twelve").append('=').append(JodaBeanUtils.toString(null)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmOptionalMeta.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.beans.MetaProperty; import com.google.common.base.Optional; /** * Mock. * @param the type */ public interface ImmOptionalMeta { /** * The meta-property for the {@code optString} property. * @return the meta-property, not null */ public abstract MetaProperty> optString(); /** * The meta-property for the {@code optStringEmpty} property. * @return the meta-property, not null */ public abstract MetaProperty> optStringEmpty(); /** * The meta-property for the {@code optStringGetter} property. * @return the meta-property, not null */ public abstract MetaProperty optStringGetter(); /** * The meta-property for the {@code optLongGetter} property. * @return the meta-property, not null */ public abstract MetaProperty optLongGetter(); /** * The meta-property for the {@code optIntGetter} property. * @return the meta-property, not null */ public abstract MetaProperty optIntGetter(); /** * The meta-property for the {@code optDoubleGetter} property. * @return the meta-property, not null */ public abstract MetaProperty optDoubleGetter(); } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmPackageScoped.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock immutable package scoped bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "package") final class ImmPackageScoped implements ImmutableBean { @PropertyDefinition(validate = "notNull") private final String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmPackageScoped}. * @return the meta-bean, not null */ public static ImmPackageScoped.Meta meta() { return ImmPackageScoped.Meta.INSTANCE; } static { MetaBean.register(ImmPackageScoped.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ static ImmPackageScoped.Builder builder() { return new ImmPackageScoped.Builder(); } /** * Creates an instance. * @param name the value of the property, not null */ ImmPackageScoped( String name) { JodaBeanUtils.notNull(name, "name"); this.name = name; } @Override public ImmPackageScoped.Meta metaBean() { return ImmPackageScoped.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public String getName() { return name; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmPackageScoped other = (ImmPackageScoped) obj; return JodaBeanUtils.equal(this.name, other.name); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(name); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmPackageScoped{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmPackageScoped}. */ static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofImmutable( this, "name", ImmPackageScoped.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public ImmPackageScoped.Builder builder() { return new ImmPackageScoped.Builder(); } @Override public Class beanType() { return ImmPackageScoped.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((ImmPackageScoped) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmPackageScoped}. */ static final class Builder extends DirectFieldsBeanBuilder { private String name; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmPackageScoped beanToCopy) { this.name = beanToCopy.getName(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3373707: // name this.name = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmPackageScoped build() { return new ImmPackageScoped( name); } //----------------------------------------------------------------------- /** * Sets the name. * @param name the new value, not null * @return this, for chaining, not null */ public Builder name(String name) { JodaBeanUtils.notNull(name, "name"); this.name = name; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmPackageScoped.Builder{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmPair.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.invoke.MethodHandles; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; /** * Mock pair, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light", factoryName = "of") public final class ImmPair implements ImmutableBean { /** * The first value. */ @PropertyDefinition private final A first; /** * The second value. */ @PropertyDefinition private final B second; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmPair}. */ private static final MetaBean META_BEAN = LightMetaBean.of( ImmPair.class, MethodHandles.lookup(), new String[] { "first", "second"}, new Object[0]); /** * The meta-bean for {@code ImmPair}. * @return the meta-bean, not null */ public static MetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * Obtains an instance. * @param the type * @param the type * @param first the value of the property * @param second the value of the property * @return the instance */ public static ImmPair of( A first, B second) { return new ImmPair<>( first, second); } private ImmPair( A first, B second) { this.first = first; this.second = second; } @Override @SuppressWarnings("unchecked") public TypedMetaBean> metaBean() { return (TypedMetaBean>) META_BEAN; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public A getFirst() { return first; } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public B getSecond() { return second; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmPair other = (ImmPair) obj; return JodaBeanUtils.equal(this.first, other.first) && JodaBeanUtils.equal(this.second, other.second); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(first); hash = hash * 31 + JodaBeanUtils.hashCode(second); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmPair{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmPerson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Date; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.ImmutableDefaults; import org.joda.beans.gen.ImmutablePreBuild; import org.joda.beans.gen.ImmutableValidator; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.Multiset; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(cacheHashCode = true, cloneStyle = "generate") public final class ImmPerson implements ImmutableBean { /** The forename. */ @PropertyDefinition private final String forename; /** The surname. */ @PropertyDefinition private final String surname; /** The number of cars. */ @PropertyDefinition @SimpleAnnotation(second = "2") private transient final int numberOfCars; /** The date of birth. */ @PropertyDefinition private transient final Date dateOfBirth; /** The middle names. */ @PropertyDefinition private transient final String[] middleNames; @PropertyDefinition private final ImmutableList

addressList; @PropertyDefinition private final Map otherAddressMap; @PropertyDefinition private final List> addressesList; @PropertyDefinition private final ImmAddress mainAddress; @PropertyDefinition private final ImmutableMultiset codeCounts; @DerivedProperty @SimpleAnnotation(first = "1") public int getAge() { return 12; } @ImmutableValidator private void validate() { if (getSurname() == null && getForename() == null) { throw new IllegalArgumentException(); } } @ImmutableDefaults private static void applyDefaults(Builder builder) { builder.numberOfCars(1); // default numberOfCars to one } @ImmutablePreBuild private static void preBuild(Builder builder) { if (builder.middleNames == null) { builder.middleNames = new String[0]; } } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmPerson}. * @return the meta-bean, not null */ public static ImmPerson.Meta meta() { return ImmPerson.Meta.INSTANCE; } static { MetaBean.register(ImmPerson.Meta.INSTANCE); } /** * The cached hash code, using the racy single-check idiom. */ private transient int cacheHashCode; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmPerson.Builder builder() { return new ImmPerson.Builder(); } private ImmPerson( String forename, String surname, int numberOfCars, Date dateOfBirth, String[] middleNames, List
addressList, Map otherAddressMap, List> addressesList, ImmAddress mainAddress, Multiset codeCounts) { this.forename = forename; this.surname = surname; this.numberOfCars = numberOfCars; this.dateOfBirth = (dateOfBirth != null ? (Date) dateOfBirth.clone() : null); this.middleNames = (middleNames != null ? middleNames.clone() : null); this.addressList = (addressList != null ? ImmutableList.copyOf(addressList) : null); this.otherAddressMap = (otherAddressMap != null ? ImmutableMap.copyOf(otherAddressMap) : null); this.addressesList = (addressesList != null ? ImmutableList.copyOf(addressesList) : null); this.mainAddress = mainAddress; this.codeCounts = (codeCounts != null ? ImmutableMultiset.copyOf(codeCounts) : null); validate(); } @Override public ImmPerson.Meta metaBean() { return ImmPerson.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public String getSurname() { return surname; } //----------------------------------------------------------------------- /** * Gets the number of cars. * @return the value of the property */ public int getNumberOfCars() { return numberOfCars; } //----------------------------------------------------------------------- /** * Gets the date of birth. * @return the value of the property */ public Date getDateOfBirth() { return (dateOfBirth != null ? (Date) dateOfBirth.clone() : null); } //----------------------------------------------------------------------- /** * Gets the middle names. * @return the value of the property */ public String[] getMiddleNames() { return (middleNames != null ? middleNames.clone() : null); } //----------------------------------------------------------------------- /** * Gets the addressList. * @return the value of the property */ public ImmutableList
getAddressList() { return addressList; } //----------------------------------------------------------------------- /** * Gets the otherAddressMap. * @return the value of the property */ public Map getOtherAddressMap() { return otherAddressMap; } //----------------------------------------------------------------------- /** * Gets the addressesList. * @return the value of the property */ public List> getAddressesList() { return addressesList; } //----------------------------------------------------------------------- /** * Gets the mainAddress. * @return the value of the property */ public ImmAddress getMainAddress() { return mainAddress; } //----------------------------------------------------------------------- /** * Gets the codeCounts. * @return the value of the property */ public ImmutableMultiset getCodeCounts() { return codeCounts; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public ImmPerson clone() { return this; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmPerson other = (ImmPerson) obj; return JodaBeanUtils.equal(this.forename, other.forename) && JodaBeanUtils.equal(this.surname, other.surname) && (this.numberOfCars == other.numberOfCars) && JodaBeanUtils.equal(this.dateOfBirth, other.dateOfBirth) && JodaBeanUtils.equal(this.middleNames, other.middleNames) && JodaBeanUtils.equal(this.addressList, other.addressList) && JodaBeanUtils.equal(this.otherAddressMap, other.otherAddressMap) && JodaBeanUtils.equal(this.addressesList, other.addressesList) && JodaBeanUtils.equal(this.mainAddress, other.mainAddress) && JodaBeanUtils.equal(this.codeCounts, other.codeCounts); } return false; } @Override public int hashCode() { int hash = cacheHashCode; if (hash == 0) { hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(forename); hash = hash * 31 + JodaBeanUtils.hashCode(surname); hash = hash * 31 + JodaBeanUtils.hashCode(numberOfCars); hash = hash * 31 + JodaBeanUtils.hashCode(dateOfBirth); hash = hash * 31 + JodaBeanUtils.hashCode(middleNames); hash = hash * 31 + JodaBeanUtils.hashCode(addressList); hash = hash * 31 + JodaBeanUtils.hashCode(otherAddressMap); hash = hash * 31 + JodaBeanUtils.hashCode(addressesList); hash = hash * 31 + JodaBeanUtils.hashCode(mainAddress); hash = hash * 31 + JodaBeanUtils.hashCode(codeCounts); cacheHashCode = hash; } return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(384); buf.append("ImmPerson{"); buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(numberOfCars)).append(',').append(' '); buf.append("dateOfBirth").append('=').append(JodaBeanUtils.toString(dateOfBirth)).append(',').append(' '); buf.append("middleNames").append('=').append(JodaBeanUtils.toString(middleNames)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(otherAddressMap)).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(addressesList)).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(mainAddress)).append(',').append(' '); buf.append("codeCounts").append('=').append(JodaBeanUtils.toString(codeCounts)).append(',').append(' '); buf.append("age").append('=').append(JodaBeanUtils.toString(getAge())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmPerson}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofImmutable( this, "forename", ImmPerson.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofImmutable( this, "surname", ImmPerson.class, String.class); /** * The meta-property for the {@code numberOfCars} property. */ private final MetaProperty numberOfCars = DirectMetaProperty.ofImmutable( this, "numberOfCars", ImmPerson.class, Integer.TYPE); /** * The meta-property for the {@code dateOfBirth} property. */ private final MetaProperty dateOfBirth = DirectMetaProperty.ofImmutable( this, "dateOfBirth", ImmPerson.class, Date.class); /** * The meta-property for the {@code middleNames} property. */ private final MetaProperty middleNames = DirectMetaProperty.ofImmutable( this, "middleNames", ImmPerson.class, String[].class); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofImmutable( this, "addressList", ImmPerson.class, (Class) ImmutableList.class); /** * The meta-property for the {@code otherAddressMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> otherAddressMap = DirectMetaProperty.ofImmutable( this, "otherAddressMap", ImmPerson.class, (Class) Map.class); /** * The meta-property for the {@code addressesList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> addressesList = DirectMetaProperty.ofImmutable( this, "addressesList", ImmPerson.class, (Class) List.class); /** * The meta-property for the {@code mainAddress} property. */ private final MetaProperty mainAddress = DirectMetaProperty.ofImmutable( this, "mainAddress", ImmPerson.class, ImmAddress.class); /** * The meta-property for the {@code codeCounts} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> codeCounts = DirectMetaProperty.ofImmutable( this, "codeCounts", ImmPerson.class, (Class) ImmutableMultiset.class); /** * The meta-property for the {@code age} property. */ private final MetaProperty age = DirectMetaProperty.ofDerived( this, "age", ImmPerson.class, Integer.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "numberOfCars", "dateOfBirth", "middleNames", "addressList", "otherAddressMap", "addressesList", "mainAddress", "codeCounts", "age"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -386871910: // dateOfBirth return this.dateOfBirth; case 404996787: // middleNames return this.middleNames; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; case -1383758447: // codeCounts return this.codeCounts; case 96511: // age return this.age; } return super.metaPropertyGet(propertyName); } @Override public ImmPerson.Builder builder() { return new ImmPerson.Builder(); } @Override public Class beanType() { return ImmPerson.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public MetaProperty surname() { return surname; } /** * The meta-property for the {@code numberOfCars} property. * @return the meta-property, not null */ public MetaProperty numberOfCars() { return numberOfCars; } /** * The meta-property for the {@code dateOfBirth} property. * @return the meta-property, not null */ public MetaProperty dateOfBirth() { return dateOfBirth; } /** * The meta-property for the {@code middleNames} property. * @return the meta-property, not null */ public MetaProperty middleNames() { return middleNames; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public MetaProperty> addressList() { return addressList; } /** * The meta-property for the {@code otherAddressMap} property. * @return the meta-property, not null */ public MetaProperty> otherAddressMap() { return otherAddressMap; } /** * The meta-property for the {@code addressesList} property. * @return the meta-property, not null */ public MetaProperty>> addressesList() { return addressesList; } /** * The meta-property for the {@code mainAddress} property. * @return the meta-property, not null */ public MetaProperty mainAddress() { return mainAddress; } /** * The meta-property for the {@code codeCounts} property. * @return the meta-property, not null */ public MetaProperty> codeCounts() { return codeCounts; } /** * The meta-property for the {@code age} property. * @return the meta-property, not null */ public MetaProperty age() { return age; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((ImmPerson) bean).getForename(); case -1852993317: // surname return ((ImmPerson) bean).getSurname(); case 926656063: // numberOfCars return ((ImmPerson) bean).getNumberOfCars(); case -386871910: // dateOfBirth return ((ImmPerson) bean).getDateOfBirth(); case 404996787: // middleNames return ((ImmPerson) bean).getMiddleNames(); case -1377524046: // addressList return ((ImmPerson) bean).getAddressList(); case 1368089592: // otherAddressMap return ((ImmPerson) bean).getOtherAddressMap(); case -226885792: // addressesList return ((ImmPerson) bean).getAddressesList(); case -2032731141: // mainAddress return ((ImmPerson) bean).getMainAddress(); case -1383758447: // codeCounts return ((ImmPerson) bean).getCodeCounts(); case 96511: // age return ((ImmPerson) bean).getAge(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmPerson}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String forename; private String surname; private int numberOfCars; private Date dateOfBirth; private String[] middleNames; private List
addressList; private Map otherAddressMap; private List> addressesList; private ImmAddress mainAddress; private Multiset codeCounts; /** * Restricted constructor. */ private Builder() { applyDefaults(this); } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmPerson beanToCopy) { this.forename = beanToCopy.getForename(); this.surname = beanToCopy.getSurname(); this.numberOfCars = beanToCopy.getNumberOfCars(); this.dateOfBirth = (beanToCopy.getDateOfBirth() != null ? (Date) beanToCopy.getDateOfBirth().clone() : null); this.middleNames = (beanToCopy.getMiddleNames() != null ? beanToCopy.getMiddleNames().clone() : null); this.addressList = beanToCopy.getAddressList(); this.otherAddressMap = (beanToCopy.getOtherAddressMap() != null ? ImmutableMap.copyOf(beanToCopy.getOtherAddressMap()) : null); this.addressesList = (beanToCopy.getAddressesList() != null ? ImmutableList.copyOf(beanToCopy.getAddressesList()) : null); this.mainAddress = beanToCopy.getMainAddress(); this.codeCounts = beanToCopy.getCodeCounts(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -386871910: // dateOfBirth return this.dateOfBirth; case 404996787: // middleNames return this.middleNames; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; case -1383758447: // codeCounts return this.codeCounts; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 467061063: // forename this.forename = (String) newValue; break; case -1852993317: // surname this.surname = (String) newValue; break; case 926656063: // numberOfCars this.numberOfCars = (Integer) newValue; break; case -386871910: // dateOfBirth this.dateOfBirth = (Date) newValue; break; case 404996787: // middleNames this.middleNames = (String[]) newValue; break; case -1377524046: // addressList this.addressList = (List
) newValue; break; case 1368089592: // otherAddressMap this.otherAddressMap = (Map) newValue; break; case -226885792: // addressesList this.addressesList = (List>) newValue; break; case -2032731141: // mainAddress this.mainAddress = (ImmAddress) newValue; break; case -1383758447: // codeCounts this.codeCounts = (Multiset) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmPerson build() { preBuild(this); return new ImmPerson( forename, surname, numberOfCars, dateOfBirth, middleNames, addressList, otherAddressMap, addressesList, mainAddress, codeCounts); } //----------------------------------------------------------------------- /** * Sets the forename. * @param forename the new value * @return this, for chaining, not null */ public Builder forename(String forename) { this.forename = forename; return this; } /** * Sets the surname. * @param surname the new value * @return this, for chaining, not null */ public Builder surname(String surname) { this.surname = surname; return this; } /** * Sets the number of cars. * @param numberOfCars the new value * @return this, for chaining, not null */ public Builder numberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; return this; } /** * Sets the date of birth. * @param dateOfBirth the new value * @return this, for chaining, not null */ public Builder dateOfBirth(Date dateOfBirth) { this.dateOfBirth = dateOfBirth; return this; } /** * Sets the middle names. * @param middleNames the new value * @return this, for chaining, not null */ public Builder middleNames(String... middleNames) { this.middleNames = middleNames; return this; } /** * Sets the addressList. * @param addressList the new value * @return this, for chaining, not null */ public Builder addressList(List
addressList) { this.addressList = addressList; return this; } /** * Sets the {@code addressList} property in the builder * from an array of objects. * @param addressList the new value * @return this, for chaining, not null */ public Builder addressList(Address... addressList) { return addressList(ImmutableList.copyOf(addressList)); } /** * Sets the otherAddressMap. * @param otherAddressMap the new value * @return this, for chaining, not null */ public Builder otherAddressMap(Map otherAddressMap) { this.otherAddressMap = otherAddressMap; return this; } /** * Sets the addressesList. * @param addressesList the new value * @return this, for chaining, not null */ public Builder addressesList(List> addressesList) { this.addressesList = addressesList; return this; } /** * Sets the {@code addressesList} property in the builder * from an array of objects. * @param addressesList the new value * @return this, for chaining, not null */ @SafeVarargs public final Builder addressesList(List
... addressesList) { return addressesList(ImmutableList.copyOf(addressesList)); } /** * Sets the mainAddress. * @param mainAddress the new value * @return this, for chaining, not null */ public Builder mainAddress(ImmAddress mainAddress) { this.mainAddress = mainAddress; return this; } /** * Sets the codeCounts. * @param codeCounts the new value * @return this, for chaining, not null */ public Builder codeCounts(Multiset codeCounts) { this.codeCounts = codeCounts; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(384); buf.append("ImmPerson.Builder{"); buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(numberOfCars)).append(',').append(' '); buf.append("dateOfBirth").append('=').append(JodaBeanUtils.toString(dateOfBirth)).append(',').append(' '); buf.append("middleNames").append('=').append(JodaBeanUtils.toString(middleNames)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(otherAddressMap)).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(addressesList)).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(mainAddress)).append(',').append(' '); buf.append("codeCounts").append('=').append(JodaBeanUtils.toString(codeCounts)).append(',').append(' '); buf.append("age").append('=').append(JodaBeanUtils.toString(null)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmPersonAbstract.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "public") public abstract class ImmPersonAbstract implements ImmutableBean { /** The forename. */ @PropertyDefinition private final String forename; /** The surname. */ @PropertyDefinition private final String surname; @DerivedProperty public int getAge() { return 12; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmPersonAbstract}. * @return the meta-bean, not null */ public static ImmPersonAbstract.Meta meta() { return ImmPersonAbstract.Meta.INSTANCE; } static { MetaBean.register(ImmPersonAbstract.Meta.INSTANCE); } /** * Creates an instance. * @param forename the value of the property * @param surname the value of the property */ public ImmPersonAbstract( String forename, String surname) { this.forename = forename; this.surname = surname; } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected ImmPersonAbstract(ImmPersonAbstract.Builder builder) { this.forename = builder.forename; this.surname = builder.surname; } @Override public ImmPersonAbstract.Meta metaBean() { return ImmPersonAbstract.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public String getSurname() { return surname; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public abstract Builder toBuilder(); @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmPersonAbstract other = (ImmPersonAbstract) obj; return JodaBeanUtils.equal(this.forename, other.forename) && JodaBeanUtils.equal(this.surname, other.surname); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(forename); hash = hash * 31 + JodaBeanUtils.hashCode(surname); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("ImmPersonAbstract{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("age").append('=').append(JodaBeanUtils.toString(getAge())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmPersonAbstract}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofImmutable( this, "forename", ImmPersonAbstract.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofImmutable( this, "surname", ImmPersonAbstract.class, String.class); /** * The meta-property for the {@code age} property. */ private final MetaProperty age = DirectMetaProperty.ofDerived( this, "age", ImmPersonAbstract.class, Integer.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "age"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 96511: // age return this.age; } return super.metaPropertyGet(propertyName); } @Override public boolean isBuildable() { return false; } @Override public ImmPersonAbstract.Builder builder() { throw new UnsupportedOperationException("ImmPersonAbstract is an abstract class"); } @Override public Class beanType() { return ImmPersonAbstract.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public final MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public final MetaProperty surname() { return surname; } /** * The meta-property for the {@code age} property. * @return the meta-property, not null */ public final MetaProperty age() { return age; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((ImmPersonAbstract) bean).getForename(); case -1852993317: // surname return ((ImmPersonAbstract) bean).getSurname(); case 96511: // age return ((ImmPersonAbstract) bean).getAge(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmPersonAbstract}. */ public abstract static class Builder extends DirectFieldsBeanBuilder { private String forename; private String surname; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(ImmPersonAbstract beanToCopy) { this.forename = beanToCopy.getForename(); this.surname = beanToCopy.getSurname(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 467061063: // forename this.forename = (String) newValue; break; case -1852993317: // surname this.surname = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } //----------------------------------------------------------------------- /** * Sets the forename. * @param forename the new value * @return this, for chaining, not null */ public Builder forename(String forename) { this.forename = forename; return this; } /** * Sets the surname. * @param surname the new value * @return this, for chaining, not null */ public Builder surname(String surname) { this.surname = surname; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("ImmPersonAbstract.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("age").append('=').append(JodaBeanUtils.toString(null)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmPersonNonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "package") public class ImmPersonNonFinal implements ImmutableBean { /** The forename. */ @PropertyDefinition private final String forename; /** The surname. */ @PropertyDefinition private final String surname; @DerivedProperty public int getAge() { return 12; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmPersonNonFinal}. * @return the meta-bean, not null */ public static ImmPersonNonFinal.Meta meta() { return ImmPersonNonFinal.Meta.INSTANCE; } static { MetaBean.register(ImmPersonNonFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmPersonNonFinal.Builder builder() { return new ImmPersonNonFinal.Builder(); } /** * Creates an instance. * @param forename the value of the property * @param surname the value of the property */ ImmPersonNonFinal( String forename, String surname) { this.forename = forename; this.surname = surname; } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected ImmPersonNonFinal(ImmPersonNonFinal.Builder builder) { this.forename = builder.forename; this.surname = builder.surname; } @Override public ImmPersonNonFinal.Meta metaBean() { return ImmPersonNonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public String getSurname() { return surname; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmPersonNonFinal other = (ImmPersonNonFinal) obj; return JodaBeanUtils.equal(this.forename, other.forename) && JodaBeanUtils.equal(this.surname, other.surname); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(forename); hash = hash * 31 + JodaBeanUtils.hashCode(surname); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("ImmPersonNonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("age").append('=').append(JodaBeanUtils.toString(getAge())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmPersonNonFinal}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofImmutable( this, "forename", ImmPersonNonFinal.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofImmutable( this, "surname", ImmPersonNonFinal.class, String.class); /** * The meta-property for the {@code age} property. */ private final MetaProperty age = DirectMetaProperty.ofDerived( this, "age", ImmPersonNonFinal.class, Integer.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "age"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 96511: // age return this.age; } return super.metaPropertyGet(propertyName); } @Override public ImmPersonNonFinal.Builder builder() { return new ImmPersonNonFinal.Builder(); } @Override public Class beanType() { return ImmPersonNonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public final MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public final MetaProperty surname() { return surname; } /** * The meta-property for the {@code age} property. * @return the meta-property, not null */ public final MetaProperty age() { return age; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((ImmPersonNonFinal) bean).getForename(); case -1852993317: // surname return ((ImmPersonNonFinal) bean).getSurname(); case 96511: // age return ((ImmPersonNonFinal) bean).getAge(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmPersonNonFinal}. */ public static class Builder extends DirectFieldsBeanBuilder { private String forename; private String surname; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(ImmPersonNonFinal beanToCopy) { this.forename = beanToCopy.getForename(); this.surname = beanToCopy.getSurname(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 467061063: // forename this.forename = (String) newValue; break; case -1852993317: // surname this.surname = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmPersonNonFinal build() { return new ImmPersonNonFinal(this); } //----------------------------------------------------------------------- /** * Sets the forename. * @param forename the new value * @return this, for chaining, not null */ public Builder forename(String forename) { this.forename = forename; return this; } /** * Sets the surname. * @param surname the new value * @return this, for chaining, not null */ public Builder surname(String surname) { this.surname = surname; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("ImmPersonNonFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("age").append('=').append(JodaBeanUtils.toString(null)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmPrivateMeta.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(metaScope = "private") public final class ImmPrivateMeta implements ImmutableBean { /** * The number. */ @PropertyDefinition private final int number; /** * The street. */ @PropertyDefinition(validate = "notNull") private final String street; /** * The city. */ @PropertyDefinition(validate = "notNull") private final String city; /** * The owner. */ @PropertyDefinition(validate = "notNull") private final ImmPerson owner; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmPrivateMeta}. * @return the meta-bean, not null */ public static MetaBean meta() { return ImmPrivateMeta.Meta.INSTANCE; } static { MetaBean.register(ImmPrivateMeta.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmPrivateMeta.Builder builder() { return new ImmPrivateMeta.Builder(); } private ImmPrivateMeta( int number, String street, String city, ImmPerson owner) { JodaBeanUtils.notNull(street, "street"); JodaBeanUtils.notNull(city, "city"); JodaBeanUtils.notNull(owner, "owner"); this.number = number; this.street = street; this.city = city; this.owner = owner; } @Override public MetaBean metaBean() { return ImmPrivateMeta.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the street. * @return the value of the property, not null */ public String getStreet() { return street; } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property, not null */ public ImmPerson getOwner() { return owner; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmPrivateMeta other = (ImmPrivateMeta) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.city, other.city) && JodaBeanUtils.equal(this.owner, other.owner); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(city); hash = hash * 31 + JodaBeanUtils.hashCode(owner); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmPrivateMeta{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmPrivateMeta}. */ private static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code number} property. */ private final MetaProperty number = DirectMetaProperty.ofImmutable( this, "number", ImmPrivateMeta.class, Integer.TYPE); /** * The meta-property for the {@code street} property. */ private final MetaProperty street = DirectMetaProperty.ofImmutable( this, "street", ImmPrivateMeta.class, String.class); /** * The meta-property for the {@code city} property. */ private final MetaProperty city = DirectMetaProperty.ofImmutable( this, "city", ImmPrivateMeta.class, String.class); /** * The meta-property for the {@code owner} property. */ private final MetaProperty owner = DirectMetaProperty.ofImmutable( this, "owner", ImmPrivateMeta.class, ImmPerson.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "number", "street", "city", "owner"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 106164915: // owner return this.owner; } return super.metaPropertyGet(propertyName); } @Override public ImmPrivateMeta.Builder builder() { return new ImmPrivateMeta.Builder(); } @Override public Class beanType() { return ImmPrivateMeta.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1034364087: // number return ((ImmPrivateMeta) bean).getNumber(); case -891990013: // street return ((ImmPrivateMeta) bean).getStreet(); case 3053931: // city return ((ImmPrivateMeta) bean).getCity(); case 106164915: // owner return ((ImmPrivateMeta) bean).getOwner(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmPrivateMeta}. */ public static final class Builder extends DirectFieldsBeanBuilder { private int number; private String street; private String city; private ImmPerson owner; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmPrivateMeta beanToCopy) { this.number = beanToCopy.getNumber(); this.street = beanToCopy.getStreet(); this.city = beanToCopy.getCity(); this.owner = beanToCopy.getOwner(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case -891990013: // street return this.street; case 3053931: // city return this.city; case 106164915: // owner return this.owner; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (Integer) newValue; break; case -891990013: // street this.street = (String) newValue; break; case 3053931: // city this.city = (String) newValue; break; case 106164915: // owner this.owner = (ImmPerson) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmPrivateMeta build() { return new ImmPrivateMeta( number, street, city, owner); } //----------------------------------------------------------------------- /** * Sets the number. * @param number the new value * @return this, for chaining, not null */ public Builder number(int number) { this.number = number; return this; } /** * Sets the street. * @param street the new value, not null * @return this, for chaining, not null */ public Builder street(String street) { JodaBeanUtils.notNull(street, "street"); this.street = street; return this; } /** * Sets the city. * @param city the new value, not null * @return this, for chaining, not null */ public Builder city(String city) { JodaBeanUtils.notNull(city, "city"); this.city = city; return this; } /** * Sets the owner. * @param owner the new value, not null * @return this, for chaining, not null */ public Builder owner(ImmPerson owner) { JodaBeanUtils.notNull(owner, "owner"); this.owner = owner; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmPrivateMeta.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmSubPersonFromAbstract.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(hierarchy = "immutable") public class ImmSubPersonFromAbstract extends ImmPersonAbstract { /** The middle name. */ @PropertyDefinition private final String middleName; /** The list of addresses. */ @PropertyDefinition private final ImmutableList
addressList; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmSubPersonFromAbstract}. * @return the meta-bean, not null */ public static ImmSubPersonFromAbstract.Meta meta() { return ImmSubPersonFromAbstract.Meta.INSTANCE; } static { MetaBean.register(ImmSubPersonFromAbstract.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmSubPersonFromAbstract.Builder builder() { return new ImmSubPersonFromAbstract.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected ImmSubPersonFromAbstract(ImmSubPersonFromAbstract.Builder builder) { super(builder); this.middleName = builder.middleName; this.addressList = (builder.addressList != null ? ImmutableList.copyOf(builder.addressList) : null); } @Override public ImmSubPersonFromAbstract.Meta metaBean() { return ImmSubPersonFromAbstract.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the middle name. * @return the value of the property */ public String getMiddleName() { return middleName; } //----------------------------------------------------------------------- /** * Gets the list of addresses. * @return the value of the property */ public ImmutableList
getAddressList() { return addressList; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmSubPersonFromAbstract other = (ImmSubPersonFromAbstract) obj; return JodaBeanUtils.equal(this.middleName, other.middleName) && JodaBeanUtils.equal(this.addressList, other.addressList) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(middleName); hash = hash * 31 + JodaBeanUtils.hashCode(addressList); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmSubPersonFromAbstract{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(middleName)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmSubPersonFromAbstract}. */ public static class Meta extends ImmPersonAbstract.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code middleName} property. */ private final MetaProperty middleName = DirectMetaProperty.ofImmutable( this, "middleName", ImmSubPersonFromAbstract.class, String.class); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofImmutable( this, "addressList", ImmSubPersonFromAbstract.class, (Class) ImmutableList.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "middleName", "addressList"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; case -1377524046: // addressList return this.addressList; } return super.metaPropertyGet(propertyName); } @Override public ImmSubPersonFromAbstract.Builder builder() { return new ImmSubPersonFromAbstract.Builder(); } @Override public Class beanType() { return ImmSubPersonFromAbstract.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code middleName} property. * @return the meta-property, not null */ public final MetaProperty middleName() { return middleName; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public final MetaProperty> addressList() { return addressList; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -818219584: // middleName return ((ImmSubPersonFromAbstract) bean).getMiddleName(); case -1377524046: // addressList return ((ImmSubPersonFromAbstract) bean).getAddressList(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmSubPersonFromAbstract}. */ public static class Builder extends ImmPersonAbstract.Builder { private String middleName; private List
addressList; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(ImmSubPersonFromAbstract beanToCopy) { super(beanToCopy); this.middleName = beanToCopy.getMiddleName(); this.addressList = beanToCopy.getAddressList(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; case -1377524046: // addressList return this.addressList; default: return super.get(propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -818219584: // middleName this.middleName = (String) newValue; break; case -1377524046: // addressList this.addressList = (List
) newValue; break; default: super.set(propertyName, newValue); break; } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmSubPersonFromAbstract build() { return new ImmSubPersonFromAbstract(this); } //----------------------------------------------------------------------- /** * Sets the middle name. * @param middleName the new value * @return this, for chaining, not null */ public Builder middleName(String middleName) { this.middleName = middleName; return this; } /** * Sets the list of addresses. * @param addressList the new value * @return this, for chaining, not null */ public Builder addressList(List
addressList) { this.addressList = addressList; return this; } /** * Sets the {@code addressList} property in the builder * from an array of objects. * @param addressList the new value * @return this, for chaining, not null */ public Builder addressList(Address... addressList) { return addressList(ImmutableList.copyOf(addressList)); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmSubPersonFromAbstract.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(middleName)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmSubPersonNonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(hierarchy = "immutable") public class ImmSubPersonNonFinal extends ImmPersonNonFinal { /** The middle name. */ @PropertyDefinition private final String middleName; /** The list of addresses. */ @PropertyDefinition private final ImmutableList
addressList; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmSubPersonNonFinal}. * @return the meta-bean, not null */ public static ImmSubPersonNonFinal.Meta meta() { return ImmSubPersonNonFinal.Meta.INSTANCE; } static { MetaBean.register(ImmSubPersonNonFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmSubPersonNonFinal.Builder builder() { return new ImmSubPersonNonFinal.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected ImmSubPersonNonFinal(ImmSubPersonNonFinal.Builder builder) { super(builder); this.middleName = builder.middleName; this.addressList = (builder.addressList != null ? ImmutableList.copyOf(builder.addressList) : null); } @Override public ImmSubPersonNonFinal.Meta metaBean() { return ImmSubPersonNonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the middle name. * @return the value of the property */ public String getMiddleName() { return middleName; } //----------------------------------------------------------------------- /** * Gets the list of addresses. * @return the value of the property */ public ImmutableList
getAddressList() { return addressList; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmSubPersonNonFinal other = (ImmSubPersonNonFinal) obj; return JodaBeanUtils.equal(this.middleName, other.middleName) && JodaBeanUtils.equal(this.addressList, other.addressList) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(middleName); hash = hash * 31 + JodaBeanUtils.hashCode(addressList); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmSubPersonNonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(middleName)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmSubPersonNonFinal}. */ public static class Meta extends ImmPersonNonFinal.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code middleName} property. */ private final MetaProperty middleName = DirectMetaProperty.ofImmutable( this, "middleName", ImmSubPersonNonFinal.class, String.class); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofImmutable( this, "addressList", ImmSubPersonNonFinal.class, (Class) ImmutableList.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "middleName", "addressList"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; case -1377524046: // addressList return this.addressList; } return super.metaPropertyGet(propertyName); } @Override public ImmSubPersonNonFinal.Builder builder() { return new ImmSubPersonNonFinal.Builder(); } @Override public Class beanType() { return ImmSubPersonNonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code middleName} property. * @return the meta-property, not null */ public final MetaProperty middleName() { return middleName; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public final MetaProperty> addressList() { return addressList; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -818219584: // middleName return ((ImmSubPersonNonFinal) bean).getMiddleName(); case -1377524046: // addressList return ((ImmSubPersonNonFinal) bean).getAddressList(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmSubPersonNonFinal}. */ public static class Builder extends ImmPersonNonFinal.Builder { private String middleName; private List
addressList; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(ImmSubPersonNonFinal beanToCopy) { super(beanToCopy); this.middleName = beanToCopy.getMiddleName(); this.addressList = beanToCopy.getAddressList(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; case -1377524046: // addressList return this.addressList; default: return super.get(propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -818219584: // middleName this.middleName = (String) newValue; break; case -1377524046: // addressList this.addressList = (List
) newValue; break; default: super.set(propertyName, newValue); break; } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmSubPersonNonFinal build() { return new ImmSubPersonNonFinal(this); } //----------------------------------------------------------------------- /** * Sets the middle name. * @param middleName the new value * @return this, for chaining, not null */ public Builder middleName(String middleName) { this.middleName = middleName; return this; } /** * Sets the list of addresses. * @param addressList the new value * @return this, for chaining, not null */ public Builder addressList(List
addressList) { this.addressList = addressList; return this; } /** * Sets the {@code addressList} property in the builder * from an array of objects. * @param addressList the new value * @return this, for chaining, not null */ public Builder addressList(Address... addressList) { return addressList(ImmutableList.copyOf(addressList)); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmSubPersonNonFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(middleName)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmSubSubPersonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.Multiset; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(hierarchy = "immutable", cacheHashCode = true) public final class ImmSubSubPersonFinal extends ImmSubPersonNonFinal { @PropertyDefinition private final ImmutableMultiset codeCounts; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmSubSubPersonFinal}. * @return the meta-bean, not null */ public static ImmSubSubPersonFinal.Meta meta() { return ImmSubSubPersonFinal.Meta.INSTANCE; } static { MetaBean.register(ImmSubSubPersonFinal.Meta.INSTANCE); } /** * The cached hash code, using the racy single-check idiom. */ private transient int cacheHashCode; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmSubSubPersonFinal.Builder builder() { return new ImmSubSubPersonFinal.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ private ImmSubSubPersonFinal(ImmSubSubPersonFinal.Builder builder) { super(builder); this.codeCounts = (builder.codeCounts != null ? ImmutableMultiset.copyOf(builder.codeCounts) : null); } @Override public ImmSubSubPersonFinal.Meta metaBean() { return ImmSubSubPersonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the codeCounts. * @return the value of the property */ public ImmutableMultiset getCodeCounts() { return codeCounts; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmSubSubPersonFinal other = (ImmSubSubPersonFinal) obj; return JodaBeanUtils.equal(this.codeCounts, other.codeCounts) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = cacheHashCode; if (hash == 0) { hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(codeCounts); hash = hash ^ super.hashCode(); cacheHashCode = hash; } return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmSubSubPersonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("codeCounts").append('=').append(JodaBeanUtils.toString(codeCounts)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmSubSubPersonFinal}. */ public static final class Meta extends ImmSubPersonNonFinal.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code codeCounts} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> codeCounts = DirectMetaProperty.ofImmutable( this, "codeCounts", ImmSubSubPersonFinal.class, (Class) ImmutableMultiset.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "codeCounts"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1383758447: // codeCounts return this.codeCounts; } return super.metaPropertyGet(propertyName); } @Override public ImmSubSubPersonFinal.Builder builder() { return new ImmSubSubPersonFinal.Builder(); } @Override public Class beanType() { return ImmSubSubPersonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code codeCounts} property. * @return the meta-property, not null */ public MetaProperty> codeCounts() { return codeCounts; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1383758447: // codeCounts return ((ImmSubSubPersonFinal) bean).getCodeCounts(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmSubSubPersonFinal}. */ public static final class Builder extends ImmSubPersonNonFinal.Builder { private Multiset codeCounts; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmSubSubPersonFinal beanToCopy) { super(beanToCopy); this.codeCounts = beanToCopy.getCodeCounts(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1383758447: // codeCounts return this.codeCounts; default: return super.get(propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1383758447: // codeCounts this.codeCounts = (Multiset) newValue; break; default: super.set(propertyName, newValue); break; } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmSubSubPersonFinal build() { return new ImmSubSubPersonFinal(this); } //----------------------------------------------------------------------- /** * Sets the codeCounts. * @param codeCounts the new value * @return this, for chaining, not null */ public Builder codeCounts(Multiset codeCounts) { this.codeCounts = codeCounts; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmSubSubPersonFinal.Builder{"); buf.append("codeCounts").append('=').append(JodaBeanUtils.toString(codeCounts)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmTolerance.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock bean for tolerance testing. * * @author Stephen Colebourne */ @BeanDefinition(cacheHashCode = true, factoryName = "create") public final class ImmTolerance implements ImmutableBean { @PropertyDefinition private final double value; @PropertyDefinition private final double[] array; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmTolerance}. * @return the meta-bean, not null */ public static ImmTolerance.Meta meta() { return ImmTolerance.Meta.INSTANCE; } static { MetaBean.register(ImmTolerance.Meta.INSTANCE); } /** * The cached hash code, using the racy single-check idiom. */ private transient int cacheHashCode; /** * Obtains an instance. * @param value the value of the property * @param array the value of the property * @return the instance */ public static ImmTolerance create( double value, double[] array) { return new ImmTolerance( value, array); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmTolerance.Builder builder() { return new ImmTolerance.Builder(); } private ImmTolerance( double value, double[] array) { this.value = value; this.array = (array != null ? array.clone() : null); } @Override public ImmTolerance.Meta metaBean() { return ImmTolerance.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property */ public double getValue() { return value; } //----------------------------------------------------------------------- /** * Gets the array. * @return the value of the property */ public double[] getArray() { return (array != null ? array.clone() : null); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmTolerance other = (ImmTolerance) obj; return JodaBeanUtils.equal(this.value, other.value) && JodaBeanUtils.equal(this.array, other.array); } return false; } @Override public int hashCode() { int hash = cacheHashCode; if (hash == 0) { hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); hash = hash * 31 + JodaBeanUtils.hashCode(array); cacheHashCode = hash; } return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmTolerance{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)).append(',').append(' '); buf.append("array").append('=').append(JodaBeanUtils.toString(array)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmTolerance}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofImmutable( this, "value", ImmTolerance.class, Double.TYPE); /** * The meta-property for the {@code array} property. */ private final MetaProperty array = DirectMetaProperty.ofImmutable( this, "array", ImmTolerance.class, double[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value", "array"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; case 93090393: // array return this.array; } return super.metaPropertyGet(propertyName); } @Override public ImmTolerance.Builder builder() { return new ImmTolerance.Builder(); } @Override public Class beanType() { return ImmTolerance.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } /** * The meta-property for the {@code array} property. * @return the meta-property, not null */ public MetaProperty array() { return array; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((ImmTolerance) bean).getValue(); case 93090393: // array return ((ImmTolerance) bean).getArray(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmTolerance}. */ public static final class Builder extends DirectFieldsBeanBuilder { private double value; private double[] array; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmTolerance beanToCopy) { this.value = beanToCopy.getValue(); this.array = (beanToCopy.getArray() != null ? beanToCopy.getArray().clone() : null); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; case 93090393: // array return this.array; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (Double) newValue; break; case 93090393: // array this.array = (double[]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmTolerance build() { return new ImmTolerance( value, array); } //----------------------------------------------------------------------- /** * Sets the value. * @param value the new value * @return this, for chaining, not null */ public Builder value(double value) { this.value = value; return this; } /** * Sets the array. * @param array the new value * @return this, for chaining, not null */ public Builder array(double... array) { this.array = array; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("ImmTolerance.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)).append(',').append(' '); buf.append("array").append('=').append(JodaBeanUtils.toString(array)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmTreeNode.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.beans.ConstructorProperties; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; /** * Mock immutable tree node, used for iterator testing. * * @author Stephen Colebourne */ @BeanDefinition(cacheHashCode = true, constructorScope = "public@ConstructorProperties", factoryName = "of") public final class ImmTreeNode implements ImmutableBean{ // NOTE: no space between ImmutableBean and { @PropertyDefinition(validate = "notNull") private final String name; @PropertyDefinition(equalsHashCodeStyle = "getter", toStringStyle = "getter") private final ImmTreeNode child1; @PropertyDefinition(equalsHashCodeStyle = "getter") private final ImmTreeNode child2; @PropertyDefinition(toStringStyle = "getter") private final ImmTreeNode child3; @PropertyDefinition(validate = "notNull", equalsHashCodeStyle = "omit", toStringStyle = "omit") private final List childList; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmTreeNode}. * @return the meta-bean, not null */ public static ImmTreeNode.Meta meta() { return ImmTreeNode.Meta.INSTANCE; } static { MetaBean.register(ImmTreeNode.Meta.INSTANCE); } /** * The cached hash code, using the racy single-check idiom. */ private transient int cacheHashCode; /** * Obtains an instance. * @param name the value of the property, not null * @param child1 the value of the property * @param child2 the value of the property * @param child3 the value of the property * @param childList the value of the property, not null * @return the instance */ public static ImmTreeNode of( String name, ImmTreeNode child1, ImmTreeNode child2, ImmTreeNode child3, List childList) { return new ImmTreeNode( name, child1, child2, child3, childList); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static ImmTreeNode.Builder builder() { return new ImmTreeNode.Builder(); } /** * Creates an instance. * @param name the value of the property, not null * @param child1 the value of the property * @param child2 the value of the property * @param child3 the value of the property * @param childList the value of the property, not null */ @ConstructorProperties({"name", "child1", "child2", "child3", "childList"}) public ImmTreeNode( String name, ImmTreeNode child1, ImmTreeNode child2, ImmTreeNode child3, List childList) { JodaBeanUtils.notNull(name, "name"); JodaBeanUtils.notNull(childList, "childList"); this.name = name; this.child1 = child1; this.child2 = child2; this.child3 = child3; this.childList = ImmutableList.copyOf(childList); } @Override public ImmTreeNode.Meta metaBean() { return ImmTreeNode.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property, not null */ public String getName() { return name; } //----------------------------------------------------------------------- /** * Gets the child1. * @return the value of the property */ public ImmTreeNode getChild1() { return child1; } //----------------------------------------------------------------------- /** * Gets the child2. * @return the value of the property */ public ImmTreeNode getChild2() { return child2; } //----------------------------------------------------------------------- /** * Gets the child3. * @return the value of the property */ public ImmTreeNode getChild3() { return child3; } //----------------------------------------------------------------------- /** * Gets the childList. * @return the value of the property, not null */ public List getChildList() { return childList; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmTreeNode other = (ImmTreeNode) obj; return JodaBeanUtils.equal(this.name, other.name) && JodaBeanUtils.equal(this.getChild1(), other.getChild1()) && JodaBeanUtils.equal(this.getChild2(), other.getChild2()) && JodaBeanUtils.equal(this.child3, other.child3); } return false; } @Override public int hashCode() { int hash = cacheHashCode; if (hash == 0) { hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(name); hash = hash * 31 + JodaBeanUtils.hashCode(getChild1()); hash = hash * 31 + JodaBeanUtils.hashCode(getChild2()); hash = hash * 31 + JodaBeanUtils.hashCode(child3); cacheHashCode = hash; } return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmTreeNode{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)).append(',').append(' '); buf.append("child1").append('=').append(JodaBeanUtils.toString(getChild1())).append(',').append(' '); buf.append("child2").append('=').append(JodaBeanUtils.toString(child2)).append(',').append(' '); buf.append("child3").append('=').append(JodaBeanUtils.toString(getChild3())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmTreeNode}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofImmutable( this, "name", ImmTreeNode.class, String.class); /** * The meta-property for the {@code child1} property. */ private final MetaProperty child1 = DirectMetaProperty.ofImmutable( this, "child1", ImmTreeNode.class, ImmTreeNode.class); /** * The meta-property for the {@code child2} property. */ private final MetaProperty child2 = DirectMetaProperty.ofImmutable( this, "child2", ImmTreeNode.class, ImmTreeNode.class); /** * The meta-property for the {@code child3} property. */ private final MetaProperty child3 = DirectMetaProperty.ofImmutable( this, "child3", ImmTreeNode.class, ImmTreeNode.class); /** * The meta-property for the {@code childList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> childList = DirectMetaProperty.ofImmutable( this, "childList", ImmTreeNode.class, (Class) List.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name", "child1", "child2", "child3", "childList"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; case -1361400171: // child1 return this.child1; case -1361400170: // child2 return this.child2; case -1361400169: // child3 return this.child3; case -95409190: // childList return this.childList; } return super.metaPropertyGet(propertyName); } @Override public ImmTreeNode.Builder builder() { return new ImmTreeNode.Builder(); } @Override public Class beanType() { return ImmTreeNode.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public MetaProperty name() { return name; } /** * The meta-property for the {@code child1} property. * @return the meta-property, not null */ public MetaProperty child1() { return child1; } /** * The meta-property for the {@code child2} property. * @return the meta-property, not null */ public MetaProperty child2() { return child2; } /** * The meta-property for the {@code child3} property. * @return the meta-property, not null */ public MetaProperty child3() { return child3; } /** * The meta-property for the {@code childList} property. * @return the meta-property, not null */ public MetaProperty> childList() { return childList; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((ImmTreeNode) bean).getName(); case -1361400171: // child1 return ((ImmTreeNode) bean).getChild1(); case -1361400170: // child2 return ((ImmTreeNode) bean).getChild2(); case -1361400169: // child3 return ((ImmTreeNode) bean).getChild3(); case -95409190: // childList return ((ImmTreeNode) bean).getChildList(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmTreeNode}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String name; private ImmTreeNode child1; private ImmTreeNode child2; private ImmTreeNode child3; private List childList = ImmutableList.of(); /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmTreeNode beanToCopy) { this.name = beanToCopy.getName(); this.child1 = beanToCopy.getChild1(); this.child2 = beanToCopy.getChild2(); this.child3 = beanToCopy.getChild3(); this.childList = ImmutableList.copyOf(beanToCopy.getChildList()); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; case -1361400171: // child1 return this.child1; case -1361400170: // child2 return this.child2; case -1361400169: // child3 return this.child3; case -95409190: // childList return this.childList; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3373707: // name this.name = (String) newValue; break; case -1361400171: // child1 this.child1 = (ImmTreeNode) newValue; break; case -1361400170: // child2 this.child2 = (ImmTreeNode) newValue; break; case -1361400169: // child3 this.child3 = (ImmTreeNode) newValue; break; case -95409190: // childList this.childList = (List) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmTreeNode build() { return new ImmTreeNode( name, child1, child2, child3, childList); } //----------------------------------------------------------------------- /** * Sets the name. * @param name the new value, not null * @return this, for chaining, not null */ public Builder name(String name) { JodaBeanUtils.notNull(name, "name"); this.name = name; return this; } /** * Sets the child1. * @param child1 the new value * @return this, for chaining, not null */ public Builder child1(ImmTreeNode child1) { this.child1 = child1; return this; } /** * Sets the child2. * @param child2 the new value * @return this, for chaining, not null */ public Builder child2(ImmTreeNode child2) { this.child2 = child2; return this; } /** * Sets the child3. * @param child3 the new value * @return this, for chaining, not null */ public Builder child3(ImmTreeNode child3) { this.child3 = child3; return this; } /** * Sets the childList. * @param childList the new value, not null * @return this, for chaining, not null */ public Builder childList(List childList) { JodaBeanUtils.notNull(childList, "childList"); this.childList = childList; return this; } /** * Sets the {@code childList} property in the builder * from an array of objects. * @param childList the new value, not null * @return this, for chaining, not null */ public Builder childList(ImmTreeNode... childList) { return childList(ImmutableList.copyOf(childList)); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("ImmTreeNode.Builder{"); buf.append("name").append('=').append(JodaBeanUtils.toString(name)).append(',').append(' '); buf.append("child1").append('=').append(JodaBeanUtils.toString(child1)).append(',').append(' '); buf.append("child2").append('=').append(JodaBeanUtils.toString(child2)).append(',').append(' '); buf.append("child3").append('=').append(JodaBeanUtils.toString(child3)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmTypes.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public", factoryName = "of") public final class ImmTypes> implements ImmutableBean { @PropertyDefinition(validate = "notNull") private final ImmutableList listWild; @PropertyDefinition(validate = "notNull", type = "List") private final List listWildPublic1; @PropertyDefinition(validate = "notNull", type = "ImmutableList") private final ImmutableList listWildPublic2; @PropertyDefinition(validate = "notNull", builderType = "List") private final List listWildBuilder1; @PropertyDefinition(validate = "notNull", builderType = "List") private final List
listWildBuilder2; @PropertyDefinition(validate = "notNull", builderType = "Map") private final Map mapWildBuilder1; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmTypes}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmTypes.Meta meta() { return ImmTypes.Meta.INSTANCE; } /** * The meta-bean for {@code ImmTypes}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static > ImmTypes.Meta metaImmTypes(Class cls) { return ImmTypes.Meta.INSTANCE; } static { MetaBean.register(ImmTypes.Meta.INSTANCE); } /** * Obtains an instance. * @param the type * @param listWild the value of the property, not null * @param listWildPublic1 the value of the property, not null * @param listWildPublic2 the value of the property, not null * @param listWildBuilder1 the value of the property, not null * @param listWildBuilder2 the value of the property, not null * @param mapWildBuilder1 the value of the property, not null * @return the instance */ public static > ImmTypes of( List listWild, List listWildPublic1, List listWildPublic2, List listWildBuilder1, List listWildBuilder2, Map mapWildBuilder1) { return new ImmTypes<>( listWild, listWildPublic1, listWildPublic2, listWildBuilder1, listWildBuilder2, mapWildBuilder1); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static > ImmTypes.Builder builder() { return new ImmTypes.Builder<>(); } private ImmTypes( List listWild, List listWildPublic1, List listWildPublic2, List listWildBuilder1, List listWildBuilder2, Map mapWildBuilder1) { JodaBeanUtils.notNull(listWild, "listWild"); JodaBeanUtils.notNull(listWildPublic1, "listWildPublic1"); JodaBeanUtils.notNull(listWildPublic2, "listWildPublic2"); JodaBeanUtils.notNull(listWildBuilder1, "listWildBuilder1"); JodaBeanUtils.notNull(listWildBuilder2, "listWildBuilder2"); JodaBeanUtils.notNull(mapWildBuilder1, "mapWildBuilder1"); this.listWild = ImmutableList.copyOf(listWild); this.listWildPublic1 = ImmutableList.copyOf(listWildPublic1); this.listWildPublic2 = ImmutableList.copyOf(listWildPublic2); this.listWildBuilder1 = ImmutableList.copyOf(listWildBuilder1); this.listWildBuilder2 = ImmutableList.copyOf(listWildBuilder2); this.mapWildBuilder1 = ImmutableMap.copyOf(mapWildBuilder1); } @SuppressWarnings("unchecked") @Override public ImmTypes.Meta metaBean() { return ImmTypes.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the listWild. * @return the value of the property, not null */ public ImmutableList getListWild() { return listWild; } //----------------------------------------------------------------------- /** * Gets the listWildPublic1. * @return the value of the property, not null */ public List getListWildPublic1() { return listWildPublic1; } //----------------------------------------------------------------------- /** * Gets the listWildPublic2. * @return the value of the property, not null */ public ImmutableList getListWildPublic2() { return listWildPublic2; } //----------------------------------------------------------------------- /** * Gets the listWildBuilder1. * @return the value of the property, not null */ public List getListWildBuilder1() { return listWildBuilder1; } //----------------------------------------------------------------------- /** * Gets the listWildBuilder2. * @return the value of the property, not null */ public List
getListWildBuilder2() { return listWildBuilder2; } //----------------------------------------------------------------------- /** * Gets the mapWildBuilder1. * @return the value of the property, not null */ public Map getMapWildBuilder1() { return mapWildBuilder1; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmTypes other = (ImmTypes) obj; return JodaBeanUtils.equal(this.listWild, other.listWild) && JodaBeanUtils.equal(this.listWildPublic1, other.listWildPublic1) && JodaBeanUtils.equal(this.listWildPublic2, other.listWildPublic2) && JodaBeanUtils.equal(this.listWildBuilder1, other.listWildBuilder1) && JodaBeanUtils.equal(this.listWildBuilder2, other.listWildBuilder2) && JodaBeanUtils.equal(this.mapWildBuilder1, other.mapWildBuilder1); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(listWild); hash = hash * 31 + JodaBeanUtils.hashCode(listWildPublic1); hash = hash * 31 + JodaBeanUtils.hashCode(listWildPublic2); hash = hash * 31 + JodaBeanUtils.hashCode(listWildBuilder1); hash = hash * 31 + JodaBeanUtils.hashCode(listWildBuilder2); hash = hash * 31 + JodaBeanUtils.hashCode(mapWildBuilder1); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("ImmTypes{"); buf.append("listWild").append('=').append(JodaBeanUtils.toString(listWild)).append(',').append(' '); buf.append("listWildPublic1").append('=').append(JodaBeanUtils.toString(listWildPublic1)).append(',').append(' '); buf.append("listWildPublic2").append('=').append(JodaBeanUtils.toString(listWildPublic2)).append(',').append(' '); buf.append("listWildBuilder1").append('=').append(JodaBeanUtils.toString(listWildBuilder1)).append(',').append(' '); buf.append("listWildBuilder2").append('=').append(JodaBeanUtils.toString(listWildBuilder2)).append(',').append(' '); buf.append("mapWildBuilder1").append('=').append(JodaBeanUtils.toString(mapWildBuilder1)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmTypes}. * @param the type */ public static final class Meta> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code listWild} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWild = DirectMetaProperty.ofImmutable( this, "listWild", ImmTypes.class, (Class) ImmutableList.class); /** * The meta-property for the {@code listWildPublic1} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildPublic1 = DirectMetaProperty.ofImmutable( this, "listWildPublic1", ImmTypes.class, (Class) List.class); /** * The meta-property for the {@code listWildPublic2} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildPublic2 = DirectMetaProperty.ofImmutable( this, "listWildPublic2", ImmTypes.class, (Class) ImmutableList.class); /** * The meta-property for the {@code listWildBuilder1} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildBuilder1 = DirectMetaProperty.ofImmutable( this, "listWildBuilder1", ImmTypes.class, (Class) List.class); /** * The meta-property for the {@code listWildBuilder2} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildBuilder2 = DirectMetaProperty.ofImmutable( this, "listWildBuilder2", ImmTypes.class, (Class) List.class); /** * The meta-property for the {@code mapWildBuilder1} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> mapWildBuilder1 = DirectMetaProperty.ofImmutable( this, "mapWildBuilder1", ImmTypes.class, (Class) Map.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "listWild", "listWildPublic1", "listWildPublic2", "listWildBuilder1", "listWildBuilder2", "mapWildBuilder1"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1345738120: // listWild return this.listWild; case 1874924608: // listWildPublic1 return this.listWildPublic1; case 1874924609: // listWildPublic2 return this.listWildPublic2; case -436161122: // listWildBuilder1 return this.listWildBuilder1; case -436161121: // listWildBuilder2 return this.listWildBuilder2; case -2009039524: // mapWildBuilder1 return this.mapWildBuilder1; } return super.metaPropertyGet(propertyName); } @Override public ImmTypes.Builder builder() { return new ImmTypes.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmTypes.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code listWild} property. * @return the meta-property, not null */ public MetaProperty> listWild() { return listWild; } /** * The meta-property for the {@code listWildPublic1} property. * @return the meta-property, not null */ public MetaProperty> listWildPublic1() { return listWildPublic1; } /** * The meta-property for the {@code listWildPublic2} property. * @return the meta-property, not null */ public MetaProperty> listWildPublic2() { return listWildPublic2; } /** * The meta-property for the {@code listWildBuilder1} property. * @return the meta-property, not null */ public MetaProperty> listWildBuilder1() { return listWildBuilder1; } /** * The meta-property for the {@code listWildBuilder2} property. * @return the meta-property, not null */ public MetaProperty> listWildBuilder2() { return listWildBuilder2; } /** * The meta-property for the {@code mapWildBuilder1} property. * @return the meta-property, not null */ public MetaProperty> mapWildBuilder1() { return mapWildBuilder1; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1345738120: // listWild return ((ImmTypes) bean).getListWild(); case 1874924608: // listWildPublic1 return ((ImmTypes) bean).getListWildPublic1(); case 1874924609: // listWildPublic2 return ((ImmTypes) bean).getListWildPublic2(); case -436161122: // listWildBuilder1 return ((ImmTypes) bean).getListWildBuilder1(); case -436161121: // listWildBuilder2 return ((ImmTypes) bean).getListWildBuilder2(); case -2009039524: // mapWildBuilder1 return ((ImmTypes) bean).getMapWildBuilder1(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmTypes}. * @param the type */ public static final class Builder> extends DirectFieldsBeanBuilder> { private List listWild = ImmutableList.of(); private List listWildPublic1 = ImmutableList.of(); private List listWildPublic2 = ImmutableList.of(); private List listWildBuilder1 = ImmutableList.of(); private List listWildBuilder2 = ImmutableList.of(); private Map mapWildBuilder1 = ImmutableMap.of(); /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmTypes beanToCopy) { this.listWild = beanToCopy.getListWild(); this.listWildPublic1 = ImmutableList.copyOf(beanToCopy.getListWildPublic1()); this.listWildPublic2 = beanToCopy.getListWildPublic2(); this.listWildBuilder1 = ImmutableList.copyOf(beanToCopy.getListWildBuilder1()); this.listWildBuilder2 = ImmutableList.copyOf(beanToCopy.getListWildBuilder2()); this.mapWildBuilder1 = ImmutableMap.copyOf(beanToCopy.getMapWildBuilder1()); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 1345738120: // listWild return this.listWild; case 1874924608: // listWildPublic1 return this.listWildPublic1; case 1874924609: // listWildPublic2 return this.listWildPublic2; case -436161122: // listWildBuilder1 return this.listWildBuilder1; case -436161121: // listWildBuilder2 return this.listWildBuilder2; case -2009039524: // mapWildBuilder1 return this.mapWildBuilder1; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 1345738120: // listWild this.listWild = (List) newValue; break; case 1874924608: // listWildPublic1 this.listWildPublic1 = (List) newValue; break; case 1874924609: // listWildPublic2 this.listWildPublic2 = (List) newValue; break; case -436161122: // listWildBuilder1 this.listWildBuilder1 = (List) newValue; break; case -436161121: // listWildBuilder2 this.listWildBuilder2 = (List) newValue; break; case -2009039524: // mapWildBuilder1 this.mapWildBuilder1 = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmTypes build() { return new ImmTypes<>( listWild, listWildPublic1, listWildPublic2, listWildBuilder1, listWildBuilder2, mapWildBuilder1); } //----------------------------------------------------------------------- /** * Sets the listWild. * @param listWild the new value, not null * @return this, for chaining, not null */ public Builder listWild(List listWild) { JodaBeanUtils.notNull(listWild, "listWild"); this.listWild = listWild; return this; } /** * Sets the {@code listWild} property in the builder * from an array of objects. * @param listWild the new value, not null * @return this, for chaining, not null */ public Builder listWild(Object... listWild) { return listWild(ImmutableList.copyOf(listWild)); } /** * Sets the listWildPublic1. * @param listWildPublic1 the new value, not null * @return this, for chaining, not null */ public Builder listWildPublic1(List listWildPublic1) { JodaBeanUtils.notNull(listWildPublic1, "listWildPublic1"); this.listWildPublic1 = listWildPublic1; return this; } /** * Sets the {@code listWildPublic1} property in the builder * from an array of objects. * @param listWildPublic1 the new value, not null * @return this, for chaining, not null */ public Builder listWildPublic1(Object... listWildPublic1) { return listWildPublic1(ImmutableList.copyOf(listWildPublic1)); } /** * Sets the listWildPublic2. * @param listWildPublic2 the new value, not null * @return this, for chaining, not null */ public Builder listWildPublic2(List listWildPublic2) { JodaBeanUtils.notNull(listWildPublic2, "listWildPublic2"); this.listWildPublic2 = listWildPublic2; return this; } /** * Sets the {@code listWildPublic2} property in the builder * from an array of objects. * @param listWildPublic2 the new value, not null * @return this, for chaining, not null */ public Builder listWildPublic2(Object... listWildPublic2) { return listWildPublic2(ImmutableList.copyOf(listWildPublic2)); } /** * Sets the listWildBuilder1. * @param listWildBuilder1 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder1(List listWildBuilder1) { JodaBeanUtils.notNull(listWildBuilder1, "listWildBuilder1"); this.listWildBuilder1 = listWildBuilder1; return this; } /** * Sets the {@code listWildBuilder1} property in the builder * from an array of objects. * @param listWildBuilder1 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder1(Object... listWildBuilder1) { return listWildBuilder1(ImmutableList.copyOf(listWildBuilder1)); } /** * Sets the listWildBuilder2. * @param listWildBuilder2 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder2(List listWildBuilder2) { JodaBeanUtils.notNull(listWildBuilder2, "listWildBuilder2"); this.listWildBuilder2 = listWildBuilder2; return this; } /** * Sets the {@code listWildBuilder2} property in the builder * from an array of objects. * @param listWildBuilder2 the new value, not null * @return this, for chaining, not null */ public Builder listWildBuilder2(Address... listWildBuilder2) { return listWildBuilder2(ImmutableList.copyOf(listWildBuilder2)); } /** * Sets the mapWildBuilder1. * @param mapWildBuilder1 the new value, not null * @return this, for chaining, not null */ public Builder mapWildBuilder1(Map mapWildBuilder1) { JodaBeanUtils.notNull(mapWildBuilder1, "mapWildBuilder1"); this.mapWildBuilder1 = mapWildBuilder1; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(224); buf.append("ImmTypes.Builder{"); buf.append("listWild").append('=').append(JodaBeanUtils.toString(listWild)).append(',').append(' '); buf.append("listWildPublic1").append('=').append(JodaBeanUtils.toString(listWildPublic1)).append(',').append(' '); buf.append("listWildPublic2").append('=').append(JodaBeanUtils.toString(listWildPublic2)).append(',').append(' '); buf.append("listWildBuilder1").append('=').append(JodaBeanUtils.toString(listWildBuilder1)).append(',').append(' '); buf.append("listWildBuilder2").append('=').append(JodaBeanUtils.toString(listWildBuilder2)).append(',').append(' '); buf.append("mapWildBuilder1").append('=').append(JodaBeanUtils.toString(mapWildBuilder1)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ImmUnusedGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "package", factoryName = "of") public final class ImmUnusedGeneric implements ImmutableBean { @PropertyDefinition(validate = "notNull") private final String errorMessage; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ImmUnusedGeneric}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ImmUnusedGeneric.Meta meta() { return ImmUnusedGeneric.Meta.INSTANCE; } /** * The meta-bean for {@code ImmUnusedGeneric}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static ImmUnusedGeneric.Meta metaImmUnusedGeneric(Class cls) { return ImmUnusedGeneric.Meta.INSTANCE; } static { MetaBean.register(ImmUnusedGeneric.Meta.INSTANCE); } /** * Obtains an instance. * @param the type * @param errorMessage the value of the property, not null * @return the instance */ public static ImmUnusedGeneric of( String errorMessage) { return new ImmUnusedGeneric<>( errorMessage); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ static ImmUnusedGeneric.Builder builder() { return new ImmUnusedGeneric.Builder<>(); } private ImmUnusedGeneric( String errorMessage) { JodaBeanUtils.notNull(errorMessage, "errorMessage"); this.errorMessage = errorMessage; } @SuppressWarnings("unchecked") @Override public ImmUnusedGeneric.Meta metaBean() { return ImmUnusedGeneric.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the errorMessage. * @return the value of the property, not null */ public String getErrorMessage() { return errorMessage; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ImmUnusedGeneric other = (ImmUnusedGeneric) obj; return JodaBeanUtils.equal(this.errorMessage, other.errorMessage); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(errorMessage); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmUnusedGeneric{"); buf.append("errorMessage").append('=').append(JodaBeanUtils.toString(errorMessage)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ImmUnusedGeneric}. * @param the type */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code errorMessage} property. */ private final MetaProperty errorMessage = DirectMetaProperty.ofImmutable( this, "errorMessage", ImmUnusedGeneric.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "errorMessage"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1203236063: // errorMessage return this.errorMessage; } return super.metaPropertyGet(propertyName); } @Override public ImmUnusedGeneric.Builder builder() { return new ImmUnusedGeneric.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) ImmUnusedGeneric.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code errorMessage} property. * @return the meta-property, not null */ public MetaProperty errorMessage() { return errorMessage; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1203236063: // errorMessage return ((ImmUnusedGeneric) bean).getErrorMessage(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code ImmUnusedGeneric}. * @param the type */ static final class Builder extends DirectFieldsBeanBuilder> { private String errorMessage; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(ImmUnusedGeneric beanToCopy) { this.errorMessage = beanToCopy.getErrorMessage(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 1203236063: // errorMessage return this.errorMessage; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 1203236063: // errorMessage this.errorMessage = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public ImmUnusedGeneric build() { return new ImmUnusedGeneric<>( errorMessage); } //----------------------------------------------------------------------- /** * Sets the errorMessage. * @param errorMessage the new value, not null * @return this, for chaining, not null */ public Builder errorMessage(String errorMessage) { JodaBeanUtils.notNull(errorMessage, "errorMessage"); this.errorMessage = errorMessage; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("ImmUnusedGeneric.Builder{"); buf.append("errorMessage").append('=').append(JodaBeanUtils.toString(errorMessage)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/JodaConvertBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.convert.FromString; import org.joda.convert.ToString; /** * A bean that is also a Joda-Convert type, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class JodaConvertBean extends DirectBean { /** * The base value. */ @PropertyDefinition private String base; /** * The extra value. */ @PropertyDefinition private int extra; public JodaConvertBean() { } @FromString public JodaConvertBean(String text) { base = text.substring(0, text.indexOf(':')); extra = Integer.parseInt(text.substring(text.indexOf(':') + 1)); } @ToString public String formattedString() { return base + ":" + extra; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code JodaConvertBean}. * @return the meta-bean, not null */ public static JodaConvertBean.Meta meta() { return JodaConvertBean.Meta.INSTANCE; } static { MetaBean.register(JodaConvertBean.Meta.INSTANCE); } @Override public JodaConvertBean.Meta metaBean() { return JodaConvertBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the base value. * @return the value of the property */ public String getBase() { return base; } /** * Sets the base value. * @param base the new value of the property */ public void setBase(String base) { this.base = base; } /** * Gets the the {@code base} property. * @return the property, not null */ public final Property base() { return metaBean().base().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the extra value. * @return the value of the property */ public int getExtra() { return extra; } /** * Sets the extra value. * @param extra the new value of the property */ public void setExtra(int extra) { this.extra = extra; } /** * Gets the the {@code extra} property. * @return the property, not null */ public final Property extra() { return metaBean().extra().createProperty(this); } //----------------------------------------------------------------------- @Override public JodaConvertBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { JodaConvertBean other = (JodaConvertBean) obj; return JodaBeanUtils.equal(this.getBase(), other.getBase()) && (this.getExtra() == other.getExtra()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getBase()); hash = hash * 31 + JodaBeanUtils.hashCode(getExtra()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("JodaConvertBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("base").append('=').append(JodaBeanUtils.toString(getBase())).append(',').append(' '); buf.append("extra").append('=').append(JodaBeanUtils.toString(getExtra())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code JodaConvertBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code base} property. */ private final MetaProperty base = DirectMetaProperty.ofReadWrite( this, "base", JodaConvertBean.class, String.class); /** * The meta-property for the {@code extra} property. */ private final MetaProperty extra = DirectMetaProperty.ofReadWrite( this, "extra", JodaConvertBean.class, Integer.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "base", "extra"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3016401: // base return this.base; case 96965648: // extra return this.extra; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new JodaConvertBean()); } @Override public Class beanType() { return JodaConvertBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code base} property. * @return the meta-property, not null */ public final MetaProperty base() { return base; } /** * The meta-property for the {@code extra} property. * @return the meta-property, not null */ public final MetaProperty extra() { return extra; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3016401: // base return ((JodaConvertBean) bean).getBase(); case 96965648: // extra return ((JodaConvertBean) bean).getExtra(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3016401: // base ((JodaConvertBean) bean).setBase((String) newValue); return; case 96965648: // extra ((JodaConvertBean) bean).setExtra((Integer) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/JodaConvertInterface.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.convert.FromString; import org.joda.convert.ToString; /** * Mock JodaConvert interface, used for testing. */ public interface JodaConvertInterface extends IKey { @FromString public static JodaConvertInterface of(String uniqueName) { return uniqueName.equalsIgnoreCase(First.INSTANCE.toString()) ? First.INSTANCE : Second.INSTANCE; } @ToString @Override public abstract String toString(); @Override public default String getName() { return toString(); } final class First implements JodaConvertInterface { static final First INSTANCE = new First(); @Override public String toString() { return "First"; } } final class Second implements JodaConvertInterface { static final Second INSTANCE = new Second(); @Override public String toString() { return "Second"; } } } ================================================ FILE: src/test/java/org/joda/beans/sample/JodaConvertWrapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Wraps {@code JodaConvertBean}, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class JodaConvertWrapper extends DirectBean { /** * The base value. */ @PropertyDefinition private JodaConvertBean bean; /** * The extra value. */ @PropertyDefinition private String description; public JodaConvertWrapper() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code JodaConvertWrapper}. * @return the meta-bean, not null */ public static JodaConvertWrapper.Meta meta() { return JodaConvertWrapper.Meta.INSTANCE; } static { MetaBean.register(JodaConvertWrapper.Meta.INSTANCE); } @Override public JodaConvertWrapper.Meta metaBean() { return JodaConvertWrapper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the base value. * @return the value of the property */ public JodaConvertBean getBean() { return bean; } /** * Sets the base value. * @param bean the new value of the property */ public void setBean(JodaConvertBean bean) { this.bean = bean; } /** * Gets the the {@code bean} property. * @return the property, not null */ public final Property bean() { return metaBean().bean().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the extra value. * @return the value of the property */ public String getDescription() { return description; } /** * Sets the extra value. * @param description the new value of the property */ public void setDescription(String description) { this.description = description; } /** * Gets the the {@code description} property. * @return the property, not null */ public final Property description() { return metaBean().description().createProperty(this); } //----------------------------------------------------------------------- @Override public JodaConvertWrapper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { JodaConvertWrapper other = (JodaConvertWrapper) obj; return JodaBeanUtils.equal(this.getBean(), other.getBean()) && JodaBeanUtils.equal(this.getDescription(), other.getDescription()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getBean()); hash = hash * 31 + JodaBeanUtils.hashCode(getDescription()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("JodaConvertWrapper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("bean").append('=').append(JodaBeanUtils.toString(getBean())).append(',').append(' '); buf.append("description").append('=').append(JodaBeanUtils.toString(getDescription())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code JodaConvertWrapper}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code bean} property. */ private final MetaProperty bean = DirectMetaProperty.ofReadWrite( this, "bean", JodaConvertWrapper.class, JodaConvertBean.class); /** * The meta-property for the {@code description} property. */ private final MetaProperty description = DirectMetaProperty.ofReadWrite( this, "description", JodaConvertWrapper.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "bean", "description"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3019696: // bean return this.bean; case -1724546052: // description return this.description; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new JodaConvertWrapper()); } @Override public Class beanType() { return JodaConvertWrapper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code bean} property. * @return the meta-property, not null */ public final MetaProperty bean() { return bean; } /** * The meta-property for the {@code description} property. * @return the meta-property, not null */ public final MetaProperty description() { return description; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3019696: // bean return ((JodaConvertWrapper) bean).getBean(); case -1724546052: // description return ((JodaConvertWrapper) bean).getDescription(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3019696: // bean ((JodaConvertWrapper) bean).setBean((JodaConvertBean) newValue); return; case -1724546052: // description ((JodaConvertWrapper) bean).setDescription((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightEmpty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.invoke.MethodHandles; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.light.LightMetaBean; /** * Mock immutable empty bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light") public final class LightEmpty implements ImmutableBean { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightEmpty}. */ private static final TypedMetaBean META_BEAN = LightMetaBean.of(LightEmpty.class, MethodHandles.lookup()); /** * The meta-bean for {@code LightEmpty}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } private LightEmpty() { } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return true; } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("LightEmpty{"); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightImmutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.lang.invoke.MethodHandles; import java.util.Currency; import java.util.List; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; /** * Mock light bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light", constructorScope = "package") public final class LightImmutable implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final int number; /** * The number. */ @PropertyDefinition private final boolean flag; /** * The street. */ @PropertyDefinition(validate = "notNull", get = "field") private final String street; /** * The town. */ @PropertyDefinition(get = "optionalGuava") private final String town; /** * The city. */ @PropertyDefinition(validate = "notNull", alias = "place") private final String city; /** * The owner. */ @PropertyDefinition(validate = "notNull") private final ImmPerson owner; /** * The list. */ @PropertyDefinition(validate = "notNull") private final ImmutableList list; /** * The currency. */ @PropertyDefinition(get = "optionalGuava") private final Currency currency; /** * The hidden text. */ @PropertyDefinition(get = "") private final String hiddenText; /** * The long. */ @PropertyDefinition private final long valueLong; /** * The short. */ @PropertyDefinition private final short valueShort; /** * The char. */ @PropertyDefinition private final char valueChar; /** * The byte. */ @PropertyDefinition private final byte valueByte; //----------------------------------------------------------------------- // manual getter with a different name public String getStreetName() { return street; } // derived @DerivedProperty public String getAddress() { return number + " " + street + " " + city; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightImmutable}. */ private static final TypedMetaBean META_BEAN = LightMetaBean.of( LightImmutable.class, MethodHandles.lookup(), new String[] { "number", "flag", "street", "town", "city", "owner", "list", "currency", "hiddenText", "valueLong", "valueShort", "valueChar", "valueByte"}, 0, Boolean.FALSE, null, null, null, null, ImmutableList.of(), null, null, 0L, (short) 0, '\u0000', (byte) 0) .withAlias("place", "city"); /** * The meta-bean for {@code LightImmutable}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Creates an instance. * @param number the value of the property * @param flag the value of the property * @param street the value of the property, not null * @param town the value of the property * @param city the value of the property, not null * @param owner the value of the property, not null * @param list the value of the property, not null * @param currency the value of the property * @param hiddenText the value of the property * @param valueLong the value of the property * @param valueShort the value of the property * @param valueChar the value of the property * @param valueByte the value of the property */ LightImmutable( int number, boolean flag, String street, String town, String city, ImmPerson owner, List list, Currency currency, String hiddenText, long valueLong, short valueShort, char valueChar, byte valueByte) { JodaBeanUtils.notNull(street, "street"); JodaBeanUtils.notNull(city, "city"); JodaBeanUtils.notNull(owner, "owner"); JodaBeanUtils.notNull(list, "list"); this.number = number; this.flag = flag; this.street = street; this.town = town; this.city = city; this.owner = owner; this.list = ImmutableList.copyOf(list); this.currency = currency; this.hiddenText = hiddenText; this.valueLong = valueLong; this.valueShort = valueShort; this.valueChar = valueChar; this.valueByte = valueByte; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public boolean isFlag() { return flag; } //----------------------------------------------------------------------- /** * Gets the town. * @return the optional value of the property, not null */ public Optional getTown() { return Optional.fromNullable(town); } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property, not null */ public ImmPerson getOwner() { return owner; } //----------------------------------------------------------------------- /** * Gets the list. * @return the value of the property, not null */ public ImmutableList getList() { return list; } //----------------------------------------------------------------------- /** * Gets the currency. * @return the optional value of the property, not null */ public Optional getCurrency() { return Optional.fromNullable(currency); } //----------------------------------------------------------------------- /** * Gets the long. * @return the value of the property */ public long getValueLong() { return valueLong; } //----------------------------------------------------------------------- /** * Gets the short. * @return the value of the property */ public short getValueShort() { return valueShort; } //----------------------------------------------------------------------- /** * Gets the char. * @return the value of the property */ public char getValueChar() { return valueChar; } //----------------------------------------------------------------------- /** * Gets the byte. * @return the value of the property */ public byte getValueByte() { return valueByte; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { LightImmutable other = (LightImmutable) obj; return (this.number == other.number) && (this.flag == other.flag) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.town, other.town) && JodaBeanUtils.equal(this.city, other.city) && JodaBeanUtils.equal(this.owner, other.owner) && JodaBeanUtils.equal(this.list, other.list) && JodaBeanUtils.equal(this.currency, other.currency) && JodaBeanUtils.equal(this.hiddenText, other.hiddenText) && (this.valueLong == other.valueLong) && (this.valueShort == other.valueShort) && (this.valueChar == other.valueChar) && (this.valueByte == other.valueByte); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(flag); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(town); hash = hash * 31 + JodaBeanUtils.hashCode(city); hash = hash * 31 + JodaBeanUtils.hashCode(owner); hash = hash * 31 + JodaBeanUtils.hashCode(list); hash = hash * 31 + JodaBeanUtils.hashCode(currency); hash = hash * 31 + JodaBeanUtils.hashCode(hiddenText); hash = hash * 31 + JodaBeanUtils.hashCode(valueLong); hash = hash * 31 + JodaBeanUtils.hashCode(valueShort); hash = hash * 31 + JodaBeanUtils.hashCode(valueChar); hash = hash * 31 + JodaBeanUtils.hashCode(valueByte); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(480); buf.append("LightImmutable{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("flag").append('=').append(JodaBeanUtils.toString(flag)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("town").append('=').append(JodaBeanUtils.toString(town)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("hiddenText").append('=').append(JodaBeanUtils.toString(hiddenText)).append(',').append(' '); buf.append("valueLong").append('=').append(JodaBeanUtils.toString(valueLong)).append(',').append(' '); buf.append("valueShort").append('=').append(JodaBeanUtils.toString(valueShort)).append(',').append(' '); buf.append("valueChar").append('=').append(JodaBeanUtils.toString(valueChar)).append(',').append(' '); buf.append("valueByte").append('=').append(JodaBeanUtils.toString(valueByte)).append(',').append(' '); buf.append("address").append('=').append(JodaBeanUtils.toString(getAddress())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightImmutableGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.lang.invoke.MethodHandles; import java.util.List; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; import com.google.common.collect.ImmutableList; /** * Mock light bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light") public final class LightImmutableGeneric implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final T number; /** * The number. */ @PropertyDefinition private final List list; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightImmutableGeneric}. */ private static final MetaBean META_BEAN = LightMetaBean.of( LightImmutableGeneric.class, MethodHandles.lookup(), new String[] { "number", "list"}, null, ImmutableList.of()); /** * The meta-bean for {@code LightImmutableGeneric}. * @return the meta-bean, not null */ public static MetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; private LightImmutableGeneric( T number, List list) { this.number = number; this.list = (list != null ? ImmutableList.copyOf(list) : null); } @Override @SuppressWarnings("unchecked") public TypedMetaBean> metaBean() { return (TypedMetaBean>) META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public T getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public List getList() { return list; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { LightImmutableGeneric other = (LightImmutableGeneric) obj; return JodaBeanUtils.equal(this.number, other.number) && JodaBeanUtils.equal(this.list, other.list); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(list); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("LightImmutableGeneric{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightImmutableSimple.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.lang.invoke.MethodHandles; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; /** * Mock light bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light", constructorScope = "package") public final class LightImmutableSimple implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final int number; /** * The text. */ @PropertyDefinition private final String text; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightImmutableSimple}. */ private static final TypedMetaBean META_BEAN = LightMetaBean.of( LightImmutableSimple.class, MethodHandles.lookup(), new String[] { "number", "text"}, new Object[0]); /** * The meta-bean for {@code LightImmutableSimple}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Creates an instance. * @param number the value of the property * @param text the value of the property */ LightImmutableSimple( int number, String text) { this.number = number; this.text = text; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the text. * @return the value of the property */ public String getText() { return text; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { LightImmutableSimple other = (LightImmutableSimple) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.text, other.text); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(text); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("LightImmutableSimple{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(text)); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightMutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Currency; import java.util.List; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; /** * Mock light bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light", constructorScope = "package") public final class LightMutable implements Bean, Serializable { /** * The number. */ @PropertyDefinition private int number; /** * The number. */ @PropertyDefinition private boolean flag; /** * The street. */ @PropertyDefinition(validate = "notNull", get = "field") private String street; /** * The text. */ @PropertyDefinition(get = "optionalGuava") private String town; /** * The city. */ @PropertyDefinition(validate = "notNull", alias = "place") private String city; /** * The list. */ @PropertyDefinition(validate = "notNull") private final List list = new ArrayList<>(); /** * The currency. */ @PropertyDefinition(get = "optionalGuava") private Currency currency; /** * The hidden text. */ @PropertyDefinition(get = "") private String hiddenText; //----------------------------------------------------------------------- // manual getter with a different name public String getStreetName() { return street; } // derived @DerivedProperty public String getAddress() { return number + " " + street + " " + city; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightMutable}. */ private static final TypedMetaBean META_BEAN = LightMetaBean.of( LightMutable.class, MethodHandles.lookup(), new String[] { "number", "flag", "street", "town", "city", "list", "currency", "hiddenText"}, 0, Boolean.FALSE, null, null, null, ImmutableList.of(), null, null) .withAlias("place", "city"); /** * The meta-bean for {@code LightMutable}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Creates an instance. * @param number the value of the property * @param flag the value of the property * @param street the value of the property, not null * @param town the value of the property * @param city the value of the property, not null * @param list the value of the property, not null * @param currency the value of the property * @param hiddenText the value of the property */ LightMutable( int number, boolean flag, String street, String town, String city, List list, Currency currency, String hiddenText) { setNumber(number); setFlag(flag); setStreet(street); setTown(town); setCity(city); setList(list); setCurrency(currency); setHiddenText(hiddenText); } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public boolean isFlag() { return flag; } /** * Sets the number. * @param flag the new value of the property */ public void setFlag(boolean flag) { this.flag = flag; } //----------------------------------------------------------------------- /** * Sets the street. * @param street the new value of the property, not null */ public void setStreet(String street) { JodaBeanUtils.notNull(street, "street"); this.street = street; } //----------------------------------------------------------------------- /** * Gets the text. * @return the optional value of the property, not null */ public Optional getTown() { return Optional.fromNullable(town); } /** * Sets the text. * @param town the new value of the property */ public void setTown(String town) { this.town = town; } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } /** * Sets the city. * @param city the new value of the property, not null */ public void setCity(String city) { JodaBeanUtils.notNull(city, "city"); this.city = city; } //----------------------------------------------------------------------- /** * Gets the list. * @return the value of the property, not null */ public List getList() { return list; } /** * Sets the list. * @param list the new value of the property, not null */ public void setList(List list) { JodaBeanUtils.notNull(list, "list"); this.list.clear(); this.list.addAll(list); } //----------------------------------------------------------------------- /** * Gets the currency. * @return the optional value of the property, not null */ public Optional getCurrency() { return Optional.fromNullable(currency); } /** * Sets the currency. * @param currency the new value of the property */ public void setCurrency(Currency currency) { this.currency = currency; } //----------------------------------------------------------------------- /** * Sets the hidden text. * @param hiddenText the new value of the property */ public void setHiddenText(String hiddenText) { this.hiddenText = hiddenText; } //----------------------------------------------------------------------- @Override public LightMutable clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { LightMutable other = (LightMutable) obj; return (this.getNumber() == other.getNumber()) && (this.isFlag() == other.isFlag()) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.town, other.town) && JodaBeanUtils.equal(this.getCity(), other.getCity()) && JodaBeanUtils.equal(this.getList(), other.getList()) && JodaBeanUtils.equal(this.currency, other.currency) && JodaBeanUtils.equal(this.hiddenText, other.hiddenText); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(isFlag()); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(town); hash = hash * 31 + JodaBeanUtils.hashCode(getCity()); hash = hash * 31 + JodaBeanUtils.hashCode(getList()); hash = hash * 31 + JodaBeanUtils.hashCode(currency); hash = hash * 31 + JodaBeanUtils.hashCode(hiddenText); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("LightMutable{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("flag").append('=').append(JodaBeanUtils.toString(isFlag())).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("town").append('=').append(JodaBeanUtils.toString(town)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(getCity())).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(getList())).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("hiddenText").append('=').append(JodaBeanUtils.toString(hiddenText)).append(',').append(' '); buf.append("address").append('=').append(JodaBeanUtils.toString(getAddress())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightMutableGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; import com.google.common.collect.ImmutableList; /** * Mock light bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light") public final class LightMutableGeneric implements Bean, Serializable { /** * The number. */ @PropertyDefinition private T number; /** * The number. */ @PropertyDefinition private final List list = new ArrayList<>(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightMutableGeneric}. */ private static final MetaBean META_BEAN = LightMetaBean.of( LightMutableGeneric.class, MethodHandles.lookup(), new String[] { "number", "list"}, null, ImmutableList.of()); /** * The meta-bean for {@code LightMutableGeneric}. * @return the meta-bean, not null */ public static MetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; private LightMutableGeneric( T number, List list) { setNumber(number); setList(list); } @Override @SuppressWarnings("unchecked") public TypedMetaBean> metaBean() { return (TypedMetaBean>) META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public T getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(T number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property, not null */ public List getList() { return list; } /** * Sets the number. * @param list the new value of the property, not null */ public void setList(List list) { JodaBeanUtils.notNull(list, "list"); this.list.clear(); this.list.addAll(list); } //----------------------------------------------------------------------- @Override public LightMutableGeneric clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { LightMutableGeneric other = (LightMutableGeneric) obj; return JodaBeanUtils.equal(this.getNumber(), other.getNumber()) && JodaBeanUtils.equal(this.getList(), other.getList()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(getList()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("LightMutableGeneric{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(getList())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/LightMutableSimple.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.lang.invoke.MethodHandles; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; /** * Mock light bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "light", constructorScope = "package") public final class LightMutableSimple implements Bean, Serializable { /** * The number. */ @PropertyDefinition private int number; /** * The text. */ @PropertyDefinition private String text; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code LightMutableSimple}. */ private static final TypedMetaBean META_BEAN = LightMetaBean.of( LightMutableSimple.class, MethodHandles.lookup(), new String[] { "number", "text"}, new Object[0]); /** * The meta-bean for {@code LightMutableSimple}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Creates an instance. * @param number the value of the property * @param text the value of the property */ LightMutableSimple( int number, String text) { setNumber(number); setText(text); } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the text. * @return the value of the property */ public String getText() { return text; } /** * Sets the text. * @param text the new value of the property */ public void setText(String text) { this.text = text; } //----------------------------------------------------------------------- @Override public LightMutableSimple clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { LightMutableSimple other = (LightMutableSimple) obj; return (this.getNumber() == other.getNumber()) && JodaBeanUtils.equal(this.getText(), other.getText()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(getText()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("LightMutableSimple{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(getText())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MetaBeanLoad.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Used only in one place to test meta-bean registration. * * @author Stephen Colebourne */ @BeanDefinition public class MetaBeanLoad implements Bean { /** The name. */ @PropertyDefinition private String name; /** * Creates an instanec. */ public MetaBeanLoad() { } /** * Creates an instanec. * * @param name the name */ public MetaBeanLoad(String name) { this.name = name; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MetaBeanLoad}. * @return the meta-bean, not null */ public static MetaBeanLoad.Meta meta() { return MetaBeanLoad.Meta.INSTANCE; } static { MetaBean.register(MetaBeanLoad.Meta.INSTANCE); } @Override public MetaBeanLoad.Meta metaBean() { return MetaBeanLoad.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property */ public void setName(String name) { this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- @Override public MetaBeanLoad clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MetaBeanLoad other = (MetaBeanLoad) obj; return JodaBeanUtils.equal(this.getName(), other.getName()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("MetaBeanLoad{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MetaBeanLoad}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", MetaBeanLoad.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "name"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new MetaBeanLoad()); } @Override public Class beanType() { return MetaBeanLoad.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((MetaBeanLoad) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((MetaBeanLoad) bean).setName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MidAbstractResult.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public abstract class MidAbstractResult extends AbstractResult { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MidAbstractResult}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static MidAbstractResult.Meta meta() { return MidAbstractResult.Meta.INSTANCE; } /** * The meta-bean for {@code MidAbstractResult}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static MidAbstractResult.Meta metaMidAbstractResult(Class cls) { return MidAbstractResult.Meta.INSTANCE; } static { MetaBean.register(MidAbstractResult.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public MidAbstractResult.Meta metaBean() { return MidAbstractResult.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("MidAbstractResult{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MidAbstractResult}. * @param the type */ public static class Meta extends AbstractResult.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap()); /** * Restricted constructor. */ protected Meta() { } @Override public boolean isBuildable() { return false; } @Override public BeanBuilder> builder() { throw new UnsupportedOperationException("MidAbstractResult is an abstract class"); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) MidAbstractResult.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalEmpty.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock immutable empty bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal") public final class MinimalEmpty implements ImmutableBean { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalEmpty}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( MinimalEmpty.class, new String[0], () -> new MinimalEmpty.Builder()); /** * The meta-bean for {@code MinimalEmpty}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MinimalEmpty.Builder builder() { return new MinimalEmpty.Builder(); } private MinimalEmpty() { } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return true; } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("MinimalEmpty{"); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code MinimalEmpty}. */ public static final class Builder extends DirectFieldsBeanBuilder { /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { throw new NoSuchElementException("Unknown property: " + propertyName); } @Override public Builder set(String propertyName, Object newValue) { throw new NoSuchElementException("Unknown property: " + propertyName); } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MinimalEmpty build() { return new MinimalEmpty(); } //----------------------------------------------------------------------- @Override public String toString() { return "MinimalEmpty.Builder{}"; } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalImmutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Currency; import java.util.List; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal", constructorScope = "package") public final class MinimalImmutable implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final int number; /** * The number. */ @PropertyDefinition private final boolean flag; /** * The street. */ @PropertyDefinition(validate = "notNull", get = "field") private final String street; /** * The town. */ @PropertyDefinition(get = "optionalGuava") private final String town; /** * The city. */ @PropertyDefinition(validate = "notNull", alias = "place") private final String city; /** * The owner. */ @PropertyDefinition(validate = "notNull") private final ImmPerson owner; /** * The list. */ @PropertyDefinition(validate = "notNull") private final ImmutableList list; /** * The currency. */ @PropertyDefinition(get = "optionalGuava") private final Currency currency; //----------------------------------------------------------------------- // manual getter with a different name public String getStreetName() { return street; } // derived @DerivedProperty public String getAddress() { return number + " " + street + " " + city; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalImmutable}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( MinimalImmutable.class, new String[] { "number", "flag", "street", "town", "city", "owner", "list", "currency"}, () -> new MinimalImmutable.Builder(), b -> b.getNumber(), b -> b.isFlag(), b -> b.street, b -> b.town, b -> b.getCity(), b -> b.getOwner(), b -> b.getList(), b -> b.currency) .withAlias("place", "city"); /** * The meta-bean for {@code MinimalImmutable}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MinimalImmutable.Builder builder() { return new MinimalImmutable.Builder(); } /** * Creates an instance. * @param number the value of the property * @param flag the value of the property * @param street the value of the property, not null * @param town the value of the property * @param city the value of the property, not null * @param owner the value of the property, not null * @param list the value of the property, not null * @param currency the value of the property */ MinimalImmutable( int number, boolean flag, String street, String town, String city, ImmPerson owner, List list, Currency currency) { JodaBeanUtils.notNull(street, "street"); JodaBeanUtils.notNull(city, "city"); JodaBeanUtils.notNull(owner, "owner"); JodaBeanUtils.notNull(list, "list"); this.number = number; this.flag = flag; this.street = street; this.town = town; this.city = city; this.owner = owner; this.list = ImmutableList.copyOf(list); this.currency = currency; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public boolean isFlag() { return flag; } //----------------------------------------------------------------------- /** * Gets the town. * @return the optional value of the property, not null */ public Optional getTown() { return Optional.fromNullable(town); } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } //----------------------------------------------------------------------- /** * Gets the owner. * @return the value of the property, not null */ public ImmPerson getOwner() { return owner; } //----------------------------------------------------------------------- /** * Gets the list. * @return the value of the property, not null */ public ImmutableList getList() { return list; } //----------------------------------------------------------------------- /** * Gets the currency. * @return the optional value of the property, not null */ public Optional getCurrency() { return Optional.fromNullable(currency); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalImmutable other = (MinimalImmutable) obj; return (this.number == other.number) && (this.flag == other.flag) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.town, other.town) && JodaBeanUtils.equal(this.city, other.city) && JodaBeanUtils.equal(this.owner, other.owner) && JodaBeanUtils.equal(this.list, other.list) && JodaBeanUtils.equal(this.currency, other.currency); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(flag); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(town); hash = hash * 31 + JodaBeanUtils.hashCode(city); hash = hash * 31 + JodaBeanUtils.hashCode(owner); hash = hash * 31 + JodaBeanUtils.hashCode(list); hash = hash * 31 + JodaBeanUtils.hashCode(currency); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("MinimalImmutable{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("flag").append('=').append(JodaBeanUtils.toString(flag)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("town").append('=').append(JodaBeanUtils.toString(town)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("address").append('=').append(JodaBeanUtils.toString(getAddress())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code MinimalImmutable}. */ public static final class Builder extends DirectFieldsBeanBuilder { private int number; private boolean flag; private String street; private String town; private String city; private ImmPerson owner; private List list = ImmutableList.of(); private Currency currency; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(MinimalImmutable beanToCopy) { this.number = beanToCopy.getNumber(); this.flag = beanToCopy.isFlag(); this.street = beanToCopy.street; this.town = beanToCopy.town; this.city = beanToCopy.getCity(); this.owner = beanToCopy.getOwner(); this.list = beanToCopy.getList(); this.currency = beanToCopy.currency; } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case 3145580: // flag return this.flag; case -891990013: // street return this.street; case 3566226: // town return this.town; case 3053931: // city case 106748167: // place (alias) return this.city; case 106164915: // owner return this.owner; case 3322014: // list return this.list; case 575402001: // currency return this.currency; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (Integer) newValue; break; case 3145580: // flag this.flag = (Boolean) newValue; break; case -891990013: // street this.street = (String) newValue; break; case 3566226: // town this.town = (String) newValue; break; case 3053931: // city case 106748167: // place (alias) this.city = (String) newValue; break; case 106164915: // owner this.owner = (ImmPerson) newValue; break; case 3322014: // list this.list = (List) newValue; break; case 575402001: // currency this.currency = (Currency) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MinimalImmutable build() { return new MinimalImmutable( number, flag, street, town, city, owner, list, currency); } //----------------------------------------------------------------------- /** * Sets the number. * @param number the new value * @return this, for chaining, not null */ public Builder number(int number) { this.number = number; return this; } /** * Sets the number. * @param flag the new value * @return this, for chaining, not null */ public Builder flag(boolean flag) { this.flag = flag; return this; } /** * Sets the street. * @param street the new value, not null * @return this, for chaining, not null */ public Builder street(String street) { JodaBeanUtils.notNull(street, "street"); this.street = street; return this; } /** * Sets the town. * @param town the new value * @return this, for chaining, not null */ public Builder town(String town) { this.town = town; return this; } /** * Sets the city. * @param city the new value, not null * @return this, for chaining, not null */ public Builder city(String city) { JodaBeanUtils.notNull(city, "city"); this.city = city; return this; } /** * Sets the owner. * @param owner the new value, not null * @return this, for chaining, not null */ public Builder owner(ImmPerson owner) { JodaBeanUtils.notNull(owner, "owner"); this.owner = owner; return this; } /** * Sets the list. * @param list the new value, not null * @return this, for chaining, not null */ public Builder list(List list) { JodaBeanUtils.notNull(list, "list"); this.list = list; return this; } /** * Sets the {@code list} property in the builder * from an array of objects. * @param list the new value, not null * @return this, for chaining, not null */ public Builder list(String... list) { return list(ImmutableList.copyOf(list)); } /** * Sets the currency. * @param currency the new value * @return this, for chaining, not null */ public Builder currency(Currency currency) { this.currency = currency; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("MinimalImmutable.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("flag").append('=').append(JodaBeanUtils.toString(flag)).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("town").append('=').append(JodaBeanUtils.toString(town)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(city)).append(',').append(' '); buf.append("owner").append('=').append(JodaBeanUtils.toString(owner)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("address").append('=').append(JodaBeanUtils.toString(null)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalImmutableGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal") public final class MinimalImmutableGeneric implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final T number; /** * The number. */ @PropertyDefinition private final List list; /** * The number. */ @PropertyDefinition private final Map map; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalImmutableGeneric}. */ @SuppressWarnings({"unchecked", "rawtypes" }) private static final MetaBean META_BEAN = MinimalMetaBean.of( MinimalImmutableGeneric.class, new String[] { "number", "list", "map"}, () -> new MinimalImmutableGeneric.Builder(), b -> b.getNumber(), b -> b.getList(), b -> b.getMap()); /** * The meta-bean for {@code MinimalImmutableGeneric}. * @return the meta-bean, not null */ public static MetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static MinimalImmutableGeneric.Builder builder() { return new MinimalImmutableGeneric.Builder<>(); } private MinimalImmutableGeneric( T number, List list, Map map) { this.number = number; this.list = (list != null ? ImmutableList.copyOf(list) : null); this.map = (map != null ? ImmutableMap.copyOf(map) : null); } @Override @SuppressWarnings("unchecked") public TypedMetaBean> metaBean() { return (TypedMetaBean>) META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public T getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public List getList() { return list; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public Map getMap() { return map; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalImmutableGeneric other = (MinimalImmutableGeneric) obj; return JodaBeanUtils.equal(this.number, other.number) && JodaBeanUtils.equal(this.list, other.list) && JodaBeanUtils.equal(this.map, other.map); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(list); hash = hash * 31 + JodaBeanUtils.hashCode(map); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("MinimalImmutableGeneric{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("map").append('=').append(JodaBeanUtils.toString(map)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code MinimalImmutableGeneric}. * @param the type */ public static final class Builder extends DirectFieldsBeanBuilder> { private T number; private List list; private Map map; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(MinimalImmutableGeneric beanToCopy) { this.number = beanToCopy.getNumber(); this.list = (beanToCopy.getList() != null ? ImmutableList.copyOf(beanToCopy.getList()) : null); this.map = (beanToCopy.getMap() != null ? ImmutableMap.copyOf(beanToCopy.getMap()) : null); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case 3322014: // list return this.list; case 107868: // map return this.map; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (T) newValue; break; case 3322014: // list this.list = (List) newValue; break; case 107868: // map this.map = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MinimalImmutableGeneric build() { return new MinimalImmutableGeneric<>( number, list, map); } //----------------------------------------------------------------------- /** * Sets the number. * @param number the new value * @return this, for chaining, not null */ public Builder number(T number) { this.number = number; return this; } /** * Sets the number. * @param list the new value * @return this, for chaining, not null */ public Builder list(List list) { this.list = list; return this; } /** * Sets the {@code list} property in the builder * from an array of objects. * @param list the new value * @return this, for chaining, not null */ @SafeVarargs public final Builder list(T... list) { return list(ImmutableList.copyOf(list)); } /** * Sets the number. * @param map the new value * @return this, for chaining, not null */ public Builder map(Map map) { this.map = map; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("MinimalImmutableGeneric.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(list)).append(',').append(' '); buf.append("map").append('=').append(JodaBeanUtils.toString(map)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalImmutableSimple.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal", constructorScope = "package") public final class MinimalImmutableSimple implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final int number; /** * The text. */ @PropertyDefinition private final String text; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalImmutableSimple}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( MinimalImmutableSimple.class, new String[] { "number", "text"}, () -> new MinimalImmutableSimple.Builder(), b -> b.getNumber(), b -> b.getText()); /** * The meta-bean for {@code MinimalImmutableSimple}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MinimalImmutableSimple.Builder builder() { return new MinimalImmutableSimple.Builder(); } /** * Creates an instance. * @param number the value of the property * @param text the value of the property */ MinimalImmutableSimple( int number, String text) { this.number = number; this.text = text; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the text. * @return the value of the property */ public String getText() { return text; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalImmutableSimple other = (MinimalImmutableSimple) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.text, other.text); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(text); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MinimalImmutableSimple{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(text)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The bean-builder for {@code MinimalImmutableSimple}. */ public static final class Builder extends DirectFieldsBeanBuilder { private int number; private String text; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(MinimalImmutableSimple beanToCopy) { this.number = beanToCopy.getNumber(); this.text = beanToCopy.getText(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1034364087: // number return this.number; case 3556653: // text return this.text; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1034364087: // number this.number = (Integer) newValue; break; case 3556653: // text this.text = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MinimalImmutableSimple build() { return new MinimalImmutableSimple( number, text); } //----------------------------------------------------------------------- /** * Sets the number. * @param number the new value * @return this, for chaining, not null */ public Builder number(int number) { this.number = number; return this; } /** * Sets the text. * @param text the new value * @return this, for chaining, not null */ public Builder text(String text) { this.text = text; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MinimalImmutableSimple.Builder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(text)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalManualBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.NoSuchElementException; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal", builderName = "Builder") public final class MinimalManualBuilder implements ImmutableBean, Serializable { /** * The number. */ @PropertyDefinition private final int number; /** * The text. */ @PropertyDefinition private final String text; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalManualBuilder}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( MinimalManualBuilder.class, new String[] { "number", "text"}, () -> new Builder(), b -> b.getNumber(), b -> b.getText()); /** * The meta-bean for {@code MinimalManualBuilder}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static Builder builder() { return new Builder(); } private MinimalManualBuilder( int number, String text) { this.number = number; this.text = text; } @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } //----------------------------------------------------------------------- /** * Gets the text. * @return the value of the property */ public String getText() { return text; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalManualBuilder other = (MinimalManualBuilder) obj; return (this.number == other.number) && JodaBeanUtils.equal(this.text, other.text); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(number); hash = hash * 31 + JodaBeanUtils.hashCode(text); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MinimalManualBuilder{"); buf.append("number").append('=').append(JodaBeanUtils.toString(number)).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(text)); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- /** * The bean-builder for {@code MinimalImmutableSimple}. */ public static final class Builder extends DirectFieldsBeanBuilder { private int number; private String text; private Builder() { } private Builder(MinimalManualBuilder beanToCopy) { this.number = beanToCopy.getNumber(); this.text = beanToCopy.getText(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName) { case "number": return number; case "text": return text; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName) { case "number": this.number = (Integer) newValue; break; case "text": this.text = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MinimalManualBuilder build() { return new MinimalManualBuilder(number, text); } //----------------------------------------------------------------------- /** * Sets the number. * @param number the new value * @return this, for chaining, not null */ public Builder number(int number) { this.number = number; return this; } /** * Sets the text. * @param text the new value * @return this, for chaining, not null */ public Builder text(String text) { this.text = text; return this; } } } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalMutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Currency; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.BasicBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; import com.google.common.base.Optional; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal") public final class MinimalMutable implements Bean, Serializable { /** * The number. */ @PropertyDefinition private int number; /** * The number. */ @PropertyDefinition private boolean flag; /** * The street. */ @PropertyDefinition(validate = "notNull", get = "field") private String street; /** * The text. */ @PropertyDefinition(get = "optionalGuava") private String town; /** * The city. */ @PropertyDefinition(validate = "notNull", alias = "place") private String city; /** * The list. */ @PropertyDefinition(validate = "notNull") private final List list = new ArrayList<>(); /** * The currency. */ @PropertyDefinition(get = "optionalGuava") private Currency currency; //----------------------------------------------------------------------- // manual getter with a different name public String getStreetName() { return street; } // derived @DerivedProperty public String getAddress() { return number + " " + street + " " + city; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalMutable}. */ @SuppressWarnings("unchecked") private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( MinimalMutable.class, new String[] { "number", "flag", "street", "town", "city", "list", "currency"}, () -> new BasicBeanBuilder<>(new MinimalMutable()), Arrays.>asList( b -> b.getNumber(), b -> b.isFlag(), b -> b.street, b -> b.town, b -> b.getCity(), b -> b.getList(), b -> b.currency), Arrays.>asList( (b, v) -> b.setNumber((Integer) v), (b, v) -> b.setFlag((Boolean) v), (b, v) -> b.setStreet((String) v), (b, v) -> b.setTown((String) v), (b, v) -> b.setCity((String) v), (b, v) -> b.setList((List) v), (b, v) -> b.setCurrency((Currency) v))) .withAlias("place", "city"); /** * The meta-bean for {@code MinimalMutable}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public boolean isFlag() { return flag; } /** * Sets the number. * @param flag the new value of the property */ public void setFlag(boolean flag) { this.flag = flag; } //----------------------------------------------------------------------- /** * Sets the street. * @param street the new value of the property, not null */ public void setStreet(String street) { JodaBeanUtils.notNull(street, "street"); this.street = street; } //----------------------------------------------------------------------- /** * Gets the text. * @return the optional value of the property, not null */ public Optional getTown() { return Optional.fromNullable(town); } /** * Sets the text. * @param town the new value of the property */ public void setTown(String town) { this.town = town; } //----------------------------------------------------------------------- /** * Gets the city. * @return the value of the property, not null */ public String getCity() { return city; } /** * Sets the city. * @param city the new value of the property, not null */ public void setCity(String city) { JodaBeanUtils.notNull(city, "city"); this.city = city; } //----------------------------------------------------------------------- /** * Gets the list. * @return the value of the property, not null */ public List getList() { return list; } /** * Sets the list. * @param list the new value of the property, not null */ public void setList(List list) { JodaBeanUtils.notNull(list, "list"); this.list.clear(); this.list.addAll(list); } //----------------------------------------------------------------------- /** * Gets the currency. * @return the optional value of the property, not null */ public Optional getCurrency() { return Optional.fromNullable(currency); } /** * Sets the currency. * @param currency the new value of the property */ public void setCurrency(Currency currency) { this.currency = currency; } //----------------------------------------------------------------------- @Override public MinimalMutable clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalMutable other = (MinimalMutable) obj; return (this.getNumber() == other.getNumber()) && (this.isFlag() == other.isFlag()) && JodaBeanUtils.equal(this.street, other.street) && JodaBeanUtils.equal(this.town, other.town) && JodaBeanUtils.equal(this.getCity(), other.getCity()) && JodaBeanUtils.equal(this.getList(), other.getList()) && JodaBeanUtils.equal(this.currency, other.currency); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(isFlag()); hash = hash * 31 + JodaBeanUtils.hashCode(street); hash = hash * 31 + JodaBeanUtils.hashCode(town); hash = hash * 31 + JodaBeanUtils.hashCode(getCity()); hash = hash * 31 + JodaBeanUtils.hashCode(getList()); hash = hash * 31 + JodaBeanUtils.hashCode(currency); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("MinimalMutable{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("flag").append('=').append(JodaBeanUtils.toString(isFlag())).append(',').append(' '); buf.append("street").append('=').append(JodaBeanUtils.toString(street)).append(',').append(' '); buf.append("town").append('=').append(JodaBeanUtils.toString(town)).append(',').append(' '); buf.append("city").append('=').append(JodaBeanUtils.toString(getCity())).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(getList())).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("address").append('=').append(JodaBeanUtils.toString(getAddress())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalMutableGeneric.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.BasicBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal") public final class MinimalMutableGeneric implements Bean, Serializable { /** * The number. */ @PropertyDefinition private T number; /** * The number. */ @PropertyDefinition private final List list = new ArrayList<>(); /** * The number. */ @PropertyDefinition private final Map map = new HashMap<>(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalMutableGeneric}. */ @SuppressWarnings({"unchecked", "rawtypes" }) private static final MetaBean META_BEAN = MinimalMetaBean.of( MinimalMutableGeneric.class, new String[] { "number", "list", "map"}, () -> new BasicBeanBuilder<>(new MinimalMutableGeneric<>()), Arrays.>asList( b -> b.getNumber(), b -> b.getList(), b -> b.getMap()), Arrays.>asList( (b, v) -> b.setNumber((Number) v), (b, v) -> b.setList((List) v), (b, v) -> b.setMap((Map) v))); /** * The meta-bean for {@code MinimalMutableGeneric}. * @return the meta-bean, not null */ public static MetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; @Override @SuppressWarnings("unchecked") public TypedMetaBean> metaBean() { return (TypedMetaBean>) META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public T getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(T number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property, not null */ public List getList() { return list; } /** * Sets the number. * @param list the new value of the property, not null */ public void setList(List list) { JodaBeanUtils.notNull(list, "list"); this.list.clear(); this.list.addAll(list); } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property, not null */ public Map getMap() { return map; } /** * Sets the number. * @param map the new value of the property, not null */ public void setMap(Map map) { JodaBeanUtils.notNull(map, "map"); this.map.clear(); this.map.putAll(map); } //----------------------------------------------------------------------- @Override public MinimalMutableGeneric clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalMutableGeneric other = (MinimalMutableGeneric) obj; return JodaBeanUtils.equal(this.getNumber(), other.getNumber()) && JodaBeanUtils.equal(this.getList(), other.getList()) && JodaBeanUtils.equal(this.getMap(), other.getMap()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(getList()); hash = hash * 31 + JodaBeanUtils.hashCode(getMap()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("MinimalMutableGeneric{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("list").append('=').append(JodaBeanUtils.toString(getList())).append(',').append(' '); buf.append("map").append('=').append(JodaBeanUtils.toString(getMap())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalMutableGenericSimple.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Arrays; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.BasicBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal") public final class MinimalMutableGenericSimple implements Bean, Serializable { /** * The number. */ @PropertyDefinition private int number; /** * The text. */ @PropertyDefinition private String text; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalMutableGenericSimple}. */ @SuppressWarnings("rawtypes") private static final MetaBean META_BEAN = MinimalMetaBean.of( MinimalMutableGenericSimple.class, new String[] { "number", "text"}, () -> new BasicBeanBuilder<>(new MinimalMutableGenericSimple<>()), Arrays.>asList( b -> b.getNumber(), b -> b.getText()), Arrays.>asList( (b, v) -> b.setNumber((Integer) v), (b, v) -> b.setText((String) v))); /** * The meta-bean for {@code MinimalMutableGenericSimple}. * @return the meta-bean, not null */ public static MetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; @Override @SuppressWarnings("unchecked") public TypedMetaBean> metaBean() { return (TypedMetaBean>) META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the text. * @return the value of the property */ public String getText() { return text; } /** * Sets the text. * @param text the new value of the property */ public void setText(String text) { this.text = text; } //----------------------------------------------------------------------- @Override public MinimalMutableGenericSimple clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalMutableGenericSimple other = (MinimalMutableGenericSimple) obj; return (this.getNumber() == other.getNumber()) && JodaBeanUtils.equal(this.getText(), other.getText()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(getText()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MinimalMutableGenericSimple{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(getText())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MinimalMutableSimple.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Arrays; import java.util.function.BiConsumer; import java.util.function.Function; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.BasicBeanBuilder; import org.joda.beans.impl.direct.MinimalMetaBean; /** * Mock minimal bean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(style = "minimal") public final class MinimalMutableSimple implements Bean, Serializable { /** * The number. */ @PropertyDefinition private int number; /** * The text. */ @PropertyDefinition private String text; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MinimalMutableSimple}. */ private static final TypedMetaBean META_BEAN = MinimalMetaBean.of( MinimalMutableSimple.class, new String[] { "number", "text"}, () -> new BasicBeanBuilder<>(new MinimalMutableSimple()), Arrays.>asList( b -> b.getNumber(), b -> b.getText()), Arrays.>asList( (b, v) -> b.setNumber((Integer) v), (b, v) -> b.setText((String) v))); /** * The meta-bean for {@code MinimalMutableSimple}. * @return the meta-bean, not null */ public static TypedMetaBean meta() { return META_BEAN; } static { MetaBean.register(META_BEAN); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } //----------------------------------------------------------------------- /** * Gets the text. * @return the value of the property */ public String getText() { return text; } /** * Sets the text. * @param text the new value of the property */ public void setText(String text) { this.text = text; } //----------------------------------------------------------------------- @Override public MinimalMutableSimple clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MinimalMutableSimple other = (MinimalMutableSimple) obj; return (this.getNumber() == other.getNumber()) && JodaBeanUtils.equal(this.getText(), other.getText()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getNumber()); hash = hash * 31 + JodaBeanUtils.hashCode(getText()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MinimalMutableSimple{"); buf.append("number").append('=').append(JodaBeanUtils.toString(getNumber())).append(',').append(' '); buf.append("text").append('=').append(JodaBeanUtils.toString(getText())); buf.append('}'); return buf.toString(); } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableBaseBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock. */ @BeanDefinition(builderScope = "public") public class MutableBaseBean implements Bean { @PropertyDefinition private String baseBeanString; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableBaseBean}. * @return the meta-bean, not null */ public static MutableBaseBean.Meta meta() { return MutableBaseBean.Meta.INSTANCE; } static { MetaBean.register(MutableBaseBean.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MutableBaseBean.Builder builder() { return new MutableBaseBean.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected MutableBaseBean(MutableBaseBean.Builder builder) { this.baseBeanString = builder.baseBeanString; } @Override public MutableBaseBean.Meta metaBean() { return MutableBaseBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the baseBeanString. * @return the value of the property */ public String getBaseBeanString() { return baseBeanString; } /** * Sets the baseBeanString. * @param baseBeanString the new value of the property */ public void setBaseBeanString(String baseBeanString) { this.baseBeanString = baseBeanString; } /** * Gets the the {@code baseBeanString} property. * @return the property, not null */ public final Property baseBeanString() { return metaBean().baseBeanString().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public MutableBaseBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableBaseBean other = (MutableBaseBean) obj; return JodaBeanUtils.equal(this.getBaseBeanString(), other.getBaseBeanString()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getBaseBeanString()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("MutableBaseBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("baseBeanString").append('=').append(JodaBeanUtils.toString(getBaseBeanString())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableBaseBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code baseBeanString} property. */ private final MetaProperty baseBeanString = DirectMetaProperty.ofReadWrite( this, "baseBeanString", MutableBaseBean.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "baseBeanString"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 788344210: // baseBeanString return this.baseBeanString; } return super.metaPropertyGet(propertyName); } @Override public MutableBaseBean.Builder builder() { return new MutableBaseBean.Builder(); } @Override public Class beanType() { return MutableBaseBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code baseBeanString} property. * @return the meta-property, not null */ public final MetaProperty baseBeanString() { return baseBeanString; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 788344210: // baseBeanString return ((MutableBaseBean) bean).getBaseBeanString(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 788344210: // baseBeanString ((MutableBaseBean) bean).setBaseBeanString((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code MutableBaseBean}. */ public static class Builder extends DirectFieldsBeanBuilder { private String baseBeanString; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(MutableBaseBean beanToCopy) { this.baseBeanString = beanToCopy.getBaseBeanString(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 788344210: // baseBeanString return this.baseBeanString; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 788344210: // baseBeanString this.baseBeanString = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MutableBaseBean build() { return new MutableBaseBean(this); } //----------------------------------------------------------------------- /** * Sets the baseBeanString. * @param baseBeanString the new value * @return this, for chaining, not null */ public Builder baseBeanString(String baseBeanString) { this.baseBeanString = baseBeanString; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("MutableBaseBean.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("baseBeanString").append('=').append(JodaBeanUtils.toString(baseBeanString)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableDeprecated.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.Optional; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class MutableDeprecated implements Cloneable, Bean { /** * The field with deprecated annotation and Javadoc tag. * @deprecated Use something else */ @Deprecated @PropertyDefinition private String deprecatedBoth; /** * The field with deprecated Javadoc tag only. * @deprecated Use something else */ @PropertyDefinition private String deprecatedJavadoc; @Deprecated @PropertyDefinition private String deprecatedAnnotation; @Deprecated @PropertyDefinition(get = "optional") private String deprecatedOptional; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableDeprecated}. * @return the meta-bean, not null */ public static MutableDeprecated.Meta meta() { return MutableDeprecated.Meta.INSTANCE; } static { MetaBean.register(MutableDeprecated.Meta.INSTANCE); } @Override public MutableDeprecated.Meta metaBean() { return MutableDeprecated.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the field with deprecated annotation and Javadoc tag. * @return the value of the property * @deprecated Use something else */ @Deprecated public String getDeprecatedBoth() { return deprecatedBoth; } /** * Sets the field with deprecated annotation and Javadoc tag. * @param deprecatedBoth the new value of the property * @deprecated Use something else */ @Deprecated public void setDeprecatedBoth(String deprecatedBoth) { this.deprecatedBoth = deprecatedBoth; } /** * Gets the the {@code deprecatedBoth} property. * @return the property, not null * @deprecated Use something else */ @Deprecated public Property deprecatedBoth() { return metaBean().deprecatedBoth().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the field with deprecated Javadoc tag only. * @return the value of the property * @deprecated Use something else */ @Deprecated public String getDeprecatedJavadoc() { return deprecatedJavadoc; } /** * Sets the field with deprecated Javadoc tag only. * @param deprecatedJavadoc the new value of the property * @deprecated Use something else */ @Deprecated public void setDeprecatedJavadoc(String deprecatedJavadoc) { this.deprecatedJavadoc = deprecatedJavadoc; } /** * Gets the the {@code deprecatedJavadoc} property. * @return the property, not null * @deprecated Use something else */ @Deprecated public Property deprecatedJavadoc() { return metaBean().deprecatedJavadoc().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the deprecatedAnnotation. * @return the value of the property * @deprecated Deprecated */ @Deprecated public String getDeprecatedAnnotation() { return deprecatedAnnotation; } /** * Sets the deprecatedAnnotation. * @param deprecatedAnnotation the new value of the property * @deprecated Deprecated */ @Deprecated public void setDeprecatedAnnotation(String deprecatedAnnotation) { this.deprecatedAnnotation = deprecatedAnnotation; } /** * Gets the the {@code deprecatedAnnotation} property. * @return the property, not null * @deprecated Deprecated */ @Deprecated public Property deprecatedAnnotation() { return metaBean().deprecatedAnnotation().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the deprecatedOptional. * @return the optional value of the property, not null * @deprecated Deprecated */ @Deprecated public Optional getDeprecatedOptional() { return Optional.ofNullable(deprecatedOptional); } /** * Sets the deprecatedOptional. * @param deprecatedOptional the new value of the property * @deprecated Deprecated */ @Deprecated public void setDeprecatedOptional(String deprecatedOptional) { this.deprecatedOptional = deprecatedOptional; } /** * Gets the the {@code deprecatedOptional} property. * @return the property, not null * @deprecated Deprecated */ @Deprecated public Property deprecatedOptional() { return metaBean().deprecatedOptional().createProperty(this); } //----------------------------------------------------------------------- @Override public MutableDeprecated clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableDeprecated other = (MutableDeprecated) obj; return JodaBeanUtils.equal(this.getDeprecatedBoth(), other.getDeprecatedBoth()) && JodaBeanUtils.equal(this.getDeprecatedJavadoc(), other.getDeprecatedJavadoc()) && JodaBeanUtils.equal(this.getDeprecatedAnnotation(), other.getDeprecatedAnnotation()) && JodaBeanUtils.equal(this.deprecatedOptional, other.deprecatedOptional); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getDeprecatedBoth()); hash = hash * 31 + JodaBeanUtils.hashCode(getDeprecatedJavadoc()); hash = hash * 31 + JodaBeanUtils.hashCode(getDeprecatedAnnotation()); hash = hash * 31 + JodaBeanUtils.hashCode(deprecatedOptional); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("MutableDeprecated{"); buf.append("deprecatedBoth").append('=').append(JodaBeanUtils.toString(getDeprecatedBoth())).append(',').append(' '); buf.append("deprecatedJavadoc").append('=').append(JodaBeanUtils.toString(getDeprecatedJavadoc())).append(',').append(' '); buf.append("deprecatedAnnotation").append('=').append(JodaBeanUtils.toString(getDeprecatedAnnotation())).append(',').append(' '); buf.append("deprecatedOptional").append('=').append(JodaBeanUtils.toString(deprecatedOptional)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableDeprecated}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code deprecatedBoth} property. */ private final MetaProperty deprecatedBoth = DirectMetaProperty.ofReadWrite( this, "deprecatedBoth", MutableDeprecated.class, String.class); /** * The meta-property for the {@code deprecatedJavadoc} property. */ private final MetaProperty deprecatedJavadoc = DirectMetaProperty.ofReadWrite( this, "deprecatedJavadoc", MutableDeprecated.class, String.class); /** * The meta-property for the {@code deprecatedAnnotation} property. */ private final MetaProperty deprecatedAnnotation = DirectMetaProperty.ofReadWrite( this, "deprecatedAnnotation", MutableDeprecated.class, String.class); /** * The meta-property for the {@code deprecatedOptional} property. */ private final MetaProperty deprecatedOptional = DirectMetaProperty.ofReadWrite( this, "deprecatedOptional", MutableDeprecated.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "deprecatedBoth", "deprecatedJavadoc", "deprecatedAnnotation", "deprecatedOptional"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth return this.deprecatedBoth; case -1632501085: // deprecatedJavadoc return this.deprecatedJavadoc; case 1044703554: // deprecatedAnnotation return this.deprecatedAnnotation; case 1434300979: // deprecatedOptional return this.deprecatedOptional; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new MutableDeprecated()); } @Override public Class beanType() { return MutableDeprecated.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code deprecatedBoth} property. * @return the meta-property, not null * @deprecated Use something else */ @Deprecated public MetaProperty deprecatedBoth() { return deprecatedBoth; } /** * The meta-property for the {@code deprecatedJavadoc} property. * @return the meta-property, not null * @deprecated Use something else */ @Deprecated public MetaProperty deprecatedJavadoc() { return deprecatedJavadoc; } /** * The meta-property for the {@code deprecatedAnnotation} property. * @return the meta-property, not null * @deprecated Deprecated */ @Deprecated public MetaProperty deprecatedAnnotation() { return deprecatedAnnotation; } /** * The meta-property for the {@code deprecatedOptional} property. * @return the meta-property, not null * @deprecated Deprecated */ @Deprecated public MetaProperty deprecatedOptional() { return deprecatedOptional; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth return ((MutableDeprecated) bean).getDeprecatedBoth(); case -1632501085: // deprecatedJavadoc return ((MutableDeprecated) bean).getDeprecatedJavadoc(); case 1044703554: // deprecatedAnnotation return ((MutableDeprecated) bean).getDeprecatedAnnotation(); case 1434300979: // deprecatedOptional return ((MutableDeprecated) bean).deprecatedOptional; } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1108081708: // deprecatedBoth ((MutableDeprecated) bean).setDeprecatedBoth((String) newValue); return; case -1632501085: // deprecatedJavadoc ((MutableDeprecated) bean).setDeprecatedJavadoc((String) newValue); return; case 1044703554: // deprecatedAnnotation ((MutableDeprecated) bean).setDeprecatedAnnotation((String) newValue); return; case 1434300979: // deprecatedOptional ((MutableDeprecated) bean).setDeprecatedOptional((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableDerived.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock bean, used for testing. */ @BeanDefinition(builderScope = "public") public class MutableDerived extends MutableEmptyBase { @PropertyDefinition private final String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableDerived}. * @return the meta-bean, not null */ public static MutableDerived.Meta meta() { return MutableDerived.Meta.INSTANCE; } static { MetaBean.register(MutableDerived.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MutableDerived.Builder builder() { return new MutableDerived.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected MutableDerived(MutableDerived.Builder builder) { super(builder); this.name = builder.name; } @Override public MutableDerived.Meta metaBean() { return MutableDerived.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property */ public String getName() { return name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public MutableDerived clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableDerived other = (MutableDerived) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("MutableDerived{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableDerived}. */ public static class Meta extends MutableEmptyBase.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadOnlyBuildable( this, "name", MutableDerived.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "name"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public MutableDerived.Builder builder() { return new MutableDerived.Builder(); } @Override public Class beanType() { return MutableDerived.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((MutableDerived) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: name"); } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code MutableDerived}. */ public static class Builder extends MutableEmptyBase.Builder { private String name; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(MutableDerived beanToCopy) { super(beanToCopy); this.name = beanToCopy.getName(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; default: return super.get(propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3373707: // name this.name = (String) newValue; break; default: super.set(propertyName, newValue); break; } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MutableDerived build() { return new MutableDerived(this); } //----------------------------------------------------------------------- /** * Sets the name. * @param name the new value * @return this, for chaining, not null */ public Builder name(String name) { this.name = name; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("MutableDerived.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(name)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableDerivedBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock. */ @BeanDefinition(builderScope = "public") public class MutableDerivedBean extends MutableBaseBean { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableDerivedBean}. * @return the meta-bean, not null */ public static MutableDerivedBean.Meta meta() { return MutableDerivedBean.Meta.INSTANCE; } static { MetaBean.register(MutableDerivedBean.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MutableDerivedBean.Builder builder() { return new MutableDerivedBean.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected MutableDerivedBean(MutableDerivedBean.Builder builder) { super(builder); } @Override public MutableDerivedBean.Meta metaBean() { return MutableDerivedBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public MutableDerivedBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("MutableDerivedBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableDerivedBean}. */ public static class Meta extends MutableBaseBean.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap()); /** * Restricted constructor. */ protected Meta() { } @Override public MutableDerivedBean.Builder builder() { return new MutableDerivedBean.Builder(); } @Override public Class beanType() { return MutableDerivedBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //----------------------------------------------------------------------- /** * The bean-builder for {@code MutableDerivedBean}. */ public static class Builder extends MutableBaseBean.Builder { /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(MutableDerivedBean beanToCopy) { super(beanToCopy); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { return super.get(propertyName); } @Override public Builder set(String propertyName, Object newValue) { super.set(propertyName, newValue); return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MutableDerivedBean build() { return new MutableDerivedBean(this); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("MutableDerivedBean.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableEmptyBase.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock bean, used for testing. */ @BeanDefinition(builderScope = "public") public class MutableEmptyBase implements Bean { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableEmptyBase}. * @return the meta-bean, not null */ public static MutableEmptyBase.Meta meta() { return MutableEmptyBase.Meta.INSTANCE; } static { MetaBean.register(MutableEmptyBase.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MutableEmptyBase.Builder builder() { return new MutableEmptyBase.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected MutableEmptyBase(MutableEmptyBase.Builder builder) { } @Override public MutableEmptyBase.Meta metaBean() { return MutableEmptyBase.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public MutableEmptyBase clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return true; } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("MutableEmptyBase{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableEmptyBase}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null); /** * Restricted constructor. */ protected Meta() { } @Override public MutableEmptyBase.Builder builder() { return new MutableEmptyBase.Builder(); } @Override public Class beanType() { return MutableEmptyBase.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //----------------------------------------------------------------------- /** * The bean-builder for {@code MutableEmptyBase}. */ public static class Builder extends DirectFieldsBeanBuilder { /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(MutableEmptyBase beanToCopy) { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { throw new NoSuchElementException("Unknown property: " + propertyName); } @Override public Builder set(String propertyName, Object newValue) { throw new NoSuchElementException("Unknown property: " + propertyName); } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MutableEmptyBase build() { return new MutableEmptyBase(this); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("MutableEmptyBase.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableListFinalBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public final class MutableListFinalBean implements Bean { @PropertyDefinition private List strings; @PropertyDefinition private Map numberMap; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableListFinalBean}. * @return the meta-bean, not null */ public static MutableListFinalBean.Meta meta() { return MutableListFinalBean.Meta.INSTANCE; } static { MetaBean.register(MutableListFinalBean.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MutableListFinalBean.Builder builder() { return new MutableListFinalBean.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ private MutableListFinalBean(MutableListFinalBean.Builder builder) { this.strings = builder.strings; this.numberMap = builder.numberMap; } @Override public MutableListFinalBean.Meta metaBean() { return MutableListFinalBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the strings. * @return the value of the property */ public List getStrings() { return strings; } /** * Sets the strings. * @param strings the new value of the property */ public void setStrings(List strings) { this.strings = strings; } /** * Gets the the {@code strings} property. * @return the property, not null */ public Property> strings() { return metaBean().strings().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the numberMap. * @return the value of the property */ public Map getNumberMap() { return numberMap; } /** * Sets the numberMap. * @param numberMap the new value of the property */ public void setNumberMap(Map numberMap) { this.numberMap = numberMap; } /** * Gets the the {@code numberMap} property. * @return the property, not null */ public Property> numberMap() { return metaBean().numberMap().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public MutableListFinalBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableListFinalBean other = (MutableListFinalBean) obj; return JodaBeanUtils.equal(this.getStrings(), other.getStrings()) && JodaBeanUtils.equal(this.getNumberMap(), other.getNumberMap()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getStrings()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberMap()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MutableListFinalBean{"); buf.append("strings").append('=').append(JodaBeanUtils.toString(getStrings())).append(',').append(' '); buf.append("numberMap").append('=').append(JodaBeanUtils.toString(getNumberMap())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableListFinalBean}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code strings} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> strings = DirectMetaProperty.ofReadWrite( this, "strings", MutableListFinalBean.class, (Class) List.class); /** * The meta-property for the {@code numberMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> numberMap = DirectMetaProperty.ofReadWrite( this, "numberMap", MutableListFinalBean.class, (Class) Map.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "strings", "numberMap"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1881759102: // strings return this.strings; case 1649910099: // numberMap return this.numberMap; } return super.metaPropertyGet(propertyName); } @Override public MutableListFinalBean.Builder builder() { return new MutableListFinalBean.Builder(); } @Override public Class beanType() { return MutableListFinalBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code strings} property. * @return the meta-property, not null */ public MetaProperty> strings() { return strings; } /** * The meta-property for the {@code numberMap} property. * @return the meta-property, not null */ public MetaProperty> numberMap() { return numberMap; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1881759102: // strings return ((MutableListFinalBean) bean).getStrings(); case 1649910099: // numberMap return ((MutableListFinalBean) bean).getNumberMap(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1881759102: // strings ((MutableListFinalBean) bean).setStrings((List) newValue); return; case 1649910099: // numberMap ((MutableListFinalBean) bean).setNumberMap((Map) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code MutableListFinalBean}. */ public static final class Builder extends DirectFieldsBeanBuilder { private List strings; private Map numberMap; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(MutableListFinalBean beanToCopy) { this.strings = (beanToCopy.getStrings() != null ? ImmutableList.copyOf(beanToCopy.getStrings()) : null); this.numberMap = (beanToCopy.getNumberMap() != null ? ImmutableMap.copyOf(beanToCopy.getNumberMap()) : null); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1881759102: // strings return this.strings; case 1649910099: // numberMap return this.numberMap; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1881759102: // strings this.strings = (List) newValue; break; case 1649910099: // numberMap this.numberMap = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MutableListFinalBean build() { return new MutableListFinalBean(this); } //----------------------------------------------------------------------- /** * Sets the strings. * @param strings the new value * @return this, for chaining, not null */ public Builder strings(List strings) { this.strings = strings; return this; } /** * Sets the {@code strings} property in the builder * from an array of objects. * @param strings the new value * @return this, for chaining, not null */ public Builder strings(String... strings) { return strings(ImmutableList.copyOf(strings)); } /** * Sets the numberMap. * @param numberMap the new value * @return this, for chaining, not null */ public Builder numberMap(Map numberMap) { this.numberMap = numberMap; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MutableListFinalBean.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("strings").append('=').append(JodaBeanUtils.toString(strings)).append(',').append(' '); buf.append("numberMap").append('=').append(JodaBeanUtils.toString(numberMap)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableListNonFinalBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public class MutableListNonFinalBean implements Bean { @PropertyDefinition private List strings; @PropertyDefinition private Map numberMap; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableListNonFinalBean}. * @return the meta-bean, not null */ public static MutableListNonFinalBean.Meta meta() { return MutableListNonFinalBean.Meta.INSTANCE; } static { MetaBean.register(MutableListNonFinalBean.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static MutableListNonFinalBean.Builder builder() { return new MutableListNonFinalBean.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected MutableListNonFinalBean(MutableListNonFinalBean.Builder builder) { this.strings = builder.strings; this.numberMap = builder.numberMap; } @Override public MutableListNonFinalBean.Meta metaBean() { return MutableListNonFinalBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the strings. * @return the value of the property */ public List getStrings() { return strings; } /** * Sets the strings. * @param strings the new value of the property */ public void setStrings(List strings) { this.strings = strings; } /** * Gets the the {@code strings} property. * @return the property, not null */ public final Property> strings() { return metaBean().strings().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the numberMap. * @return the value of the property */ public Map getNumberMap() { return numberMap; } /** * Sets the numberMap. * @param numberMap the new value of the property */ public void setNumberMap(Map numberMap) { this.numberMap = numberMap; } /** * Gets the the {@code numberMap} property. * @return the property, not null */ public final Property> numberMap() { return metaBean().numberMap().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public MutableListNonFinalBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableListNonFinalBean other = (MutableListNonFinalBean) obj; return JodaBeanUtils.equal(this.getStrings(), other.getStrings()) && JodaBeanUtils.equal(this.getNumberMap(), other.getNumberMap()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getStrings()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberMap()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MutableListNonFinalBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("strings").append('=').append(JodaBeanUtils.toString(getStrings())).append(',').append(' '); buf.append("numberMap").append('=').append(JodaBeanUtils.toString(getNumberMap())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableListNonFinalBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code strings} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> strings = DirectMetaProperty.ofReadWrite( this, "strings", MutableListNonFinalBean.class, (Class) List.class); /** * The meta-property for the {@code numberMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> numberMap = DirectMetaProperty.ofReadWrite( this, "numberMap", MutableListNonFinalBean.class, (Class) Map.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "strings", "numberMap"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -1881759102: // strings return this.strings; case 1649910099: // numberMap return this.numberMap; } return super.metaPropertyGet(propertyName); } @Override public MutableListNonFinalBean.Builder builder() { return new MutableListNonFinalBean.Builder(); } @Override public Class beanType() { return MutableListNonFinalBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code strings} property. * @return the meta-property, not null */ public final MetaProperty> strings() { return strings; } /** * The meta-property for the {@code numberMap} property. * @return the meta-property, not null */ public final MetaProperty> numberMap() { return numberMap; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -1881759102: // strings return ((MutableListNonFinalBean) bean).getStrings(); case 1649910099: // numberMap return ((MutableListNonFinalBean) bean).getNumberMap(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -1881759102: // strings ((MutableListNonFinalBean) bean).setStrings((List) newValue); return; case 1649910099: // numberMap ((MutableListNonFinalBean) bean).setNumberMap((Map) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code MutableListNonFinalBean}. */ public static class Builder extends DirectFieldsBeanBuilder { private List strings; private Map numberMap; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(MutableListNonFinalBean beanToCopy) { this.strings = (beanToCopy.getStrings() != null ? ImmutableList.copyOf(beanToCopy.getStrings()) : null); this.numberMap = (beanToCopy.getNumberMap() != null ? ImmutableMap.copyOf(beanToCopy.getNumberMap()) : null); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -1881759102: // strings return this.strings; case 1649910099: // numberMap return this.numberMap; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -1881759102: // strings this.strings = (List) newValue; break; case 1649910099: // numberMap this.numberMap = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public MutableListNonFinalBean build() { return new MutableListNonFinalBean(this); } //----------------------------------------------------------------------- /** * Sets the strings. * @param strings the new value * @return this, for chaining, not null */ public Builder strings(List strings) { this.strings = strings; return this; } /** * Sets the {@code strings} property in the builder * from an array of objects. * @param strings the new value * @return this, for chaining, not null */ public Builder strings(String... strings) { return strings(ImmutableList.copyOf(strings)); } /** * Sets the numberMap. * @param numberMap the new value * @return this, for chaining, not null */ public Builder numberMap(Map numberMap) { this.numberMap = numberMap; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MutableListNonFinalBean.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("strings").append('=').append(JodaBeanUtils.toString(strings)).append(',').append(' '); buf.append("numberMap").append('=').append(JodaBeanUtils.toString(numberMap)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableOptional.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.base.Optional; /** * Mock. */ @BeanDefinition public final class MutableOptional implements Bean { // this works but not in serialization @PropertyDefinition(validate = "notNull") private Optional optString; // these are the recommended approach, nullable fields, optional getters // remove "Guava" to test Java 8 generation @PropertyDefinition(get = "optionalGuava") private String optStringGetter; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableOptional}. * @return the meta-bean, not null */ public static MutableOptional.Meta meta() { return MutableOptional.Meta.INSTANCE; } static { MetaBean.register(MutableOptional.Meta.INSTANCE); } @Override public MutableOptional.Meta metaBean() { return MutableOptional.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the optString. * @return the value of the property, not null */ public Optional getOptString() { return optString; } /** * Sets the optString. * @param optString the new value of the property, not null */ public void setOptString(Optional optString) { JodaBeanUtils.notNull(optString, "optString"); this.optString = optString; } /** * Gets the the {@code optString} property. * @return the property, not null */ public Property> optString() { return metaBean().optString().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the optStringGetter. * @return the optional value of the property, not null */ public Optional getOptStringGetter() { return Optional.fromNullable(optStringGetter); } /** * Sets the optStringGetter. * @param optStringGetter the new value of the property */ public void setOptStringGetter(String optStringGetter) { this.optStringGetter = optStringGetter; } /** * Gets the the {@code optStringGetter} property. * @return the property, not null */ public Property optStringGetter() { return metaBean().optStringGetter().createProperty(this); } //----------------------------------------------------------------------- @Override public MutableOptional clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableOptional other = (MutableOptional) obj; return JodaBeanUtils.equal(this.getOptString(), other.getOptString()) && JodaBeanUtils.equal(this.optStringGetter, other.optStringGetter); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getOptString()); hash = hash * 31 + JodaBeanUtils.hashCode(optStringGetter); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MutableOptional{"); buf.append("optString").append('=').append(JodaBeanUtils.toString(getOptString())).append(',').append(' '); buf.append("optStringGetter").append('=').append(JodaBeanUtils.toString(optStringGetter)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableOptional}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code optString} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> optString = DirectMetaProperty.ofReadWrite( this, "optString", MutableOptional.class, (Class) Optional.class); /** * The meta-property for the {@code optStringGetter} property. */ private final MetaProperty optStringGetter = DirectMetaProperty.ofReadWrite( this, "optStringGetter", MutableOptional.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "optString", "optStringGetter"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1220339876: // optString return this.optString; case -740642097: // optStringGetter return this.optStringGetter; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new MutableOptional()); } @Override public Class beanType() { return MutableOptional.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code optString} property. * @return the meta-property, not null */ public MetaProperty> optString() { return optString; } /** * The meta-property for the {@code optStringGetter} property. * @return the meta-property, not null */ public MetaProperty optStringGetter() { return optStringGetter; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1220339876: // optString return ((MutableOptional) bean).getOptString(); case -740642097: // optStringGetter return ((MutableOptional) bean).optStringGetter; } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 1220339876: // optString ((MutableOptional) bean).setOptString((Optional) newValue); return; case -740642097: // optStringGetter ((MutableOptional) bean).setOptStringGetter((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((MutableOptional) bean).optString, "optString"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/MutableTypes.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class MutableTypes> implements Bean { // not supported, the other two options below are good enough // @PropertyDefinition(validate = "notNull") // private final List listWild = new ArrayList(); @PropertyDefinition private List listWildNullable; @PropertyDefinition(validate = "notNull", type = "List") private final List listWildPublic = new ArrayList<>(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code MutableTypes}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static MutableTypes.Meta meta() { return MutableTypes.Meta.INSTANCE; } /** * The meta-bean for {@code MutableTypes}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static > MutableTypes.Meta metaMutableTypes(Class cls) { return MutableTypes.Meta.INSTANCE; } static { MetaBean.register(MutableTypes.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public MutableTypes.Meta metaBean() { return MutableTypes.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the listWildNullable. * @return the value of the property */ public List getListWildNullable() { return listWildNullable; } /** * Sets the listWildNullable. * @param listWildNullable the new value of the property */ public void setListWildNullable(List listWildNullable) { this.listWildNullable = listWildNullable; } /** * Gets the the {@code listWildNullable} property. * @return the property, not null */ public Property> listWildNullable() { return metaBean().listWildNullable().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the listWildPublic. * @return the value of the property, not null */ public List getListWildPublic() { return listWildPublic; } /** * Sets the listWildPublic. * @param listWildPublic the new value of the property, not null */ public void setListWildPublic(List listWildPublic) { JodaBeanUtils.notNull(listWildPublic, "listWildPublic"); this.listWildPublic.clear(); this.listWildPublic.addAll(listWildPublic); } /** * Gets the the {@code listWildPublic} property. * @return the property, not null */ public Property> listWildPublic() { return metaBean().listWildPublic().createProperty(this); } //----------------------------------------------------------------------- @Override public MutableTypes clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { MutableTypes other = (MutableTypes) obj; return JodaBeanUtils.equal(this.getListWildNullable(), other.getListWildNullable()) && JodaBeanUtils.equal(this.getListWildPublic(), other.getListWildPublic()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getListWildNullable()); hash = hash * 31 + JodaBeanUtils.hashCode(getListWildPublic()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("MutableTypes{"); buf.append("listWildNullable").append('=').append(JodaBeanUtils.toString(getListWildNullable())).append(',').append(' '); buf.append("listWildPublic").append('=').append(JodaBeanUtils.toString(getListWildPublic())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code MutableTypes}. * @param the type */ public static final class Meta> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code listWildNullable} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildNullable = DirectMetaProperty.ofReadWrite( this, "listWildNullable", MutableTypes.class, (Class) List.class); /** * The meta-property for the {@code listWildPublic} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listWildPublic = DirectMetaProperty.ofReadWrite( this, "listWildPublic", MutableTypes.class, (Class) List.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "listWildNullable", "listWildPublic"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -911478519: // listWildNullable return this.listWildNullable; case -355160559: // listWildPublic return this.listWildPublic; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new MutableTypes()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) MutableTypes.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code listWildNullable} property. * @return the meta-property, not null */ public MetaProperty> listWildNullable() { return listWildNullable; } /** * The meta-property for the {@code listWildPublic} property. * @return the meta-property, not null */ public MetaProperty> listWildPublic() { return listWildPublic; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -911478519: // listWildNullable return ((MutableTypes) bean).getListWildNullable(); case -355160559: // listWildPublic return ((MutableTypes) bean).getListWildPublic(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -911478519: // listWildNullable ((MutableTypes) bean).setListWildNullable((List) newValue); return; case -355160559: // listWildPublic ((MutableTypes) bean).setListWildPublic((List) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((MutableTypes) bean).listWildPublic, "listWildPublic"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/NoClone.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock person JavaBean, used for testing. */ @BeanDefinition(cloneStyle = "omit") public class NoClone implements Bean { @PropertyDefinition private String dummyProperty; /** * Creates an instance. */ public NoClone() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code NoClone}. * @return the meta-bean, not null */ public static NoClone.Meta meta() { return NoClone.Meta.INSTANCE; } static { MetaBean.register(NoClone.Meta.INSTANCE); } @Override public NoClone.Meta metaBean() { return NoClone.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the dummyProperty. * @return the value of the property */ public String getDummyProperty() { return dummyProperty; } /** * Sets the dummyProperty. * @param dummyProperty the new value of the property */ public void setDummyProperty(String dummyProperty) { this.dummyProperty = dummyProperty; } /** * Gets the the {@code dummyProperty} property. * @return the property, not null */ public final Property dummyProperty() { return metaBean().dummyProperty().createProperty(this); } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { NoClone other = (NoClone) obj; return JodaBeanUtils.equal(this.getDummyProperty(), other.getDummyProperty()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getDummyProperty()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("NoClone{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("dummyProperty").append('=').append(JodaBeanUtils.toString(getDummyProperty())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code NoClone}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code dummyProperty} property. */ private final MetaProperty dummyProperty = DirectMetaProperty.ofReadWrite( this, "dummyProperty", NoClone.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "dummyProperty"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -184213859: // dummyProperty return this.dummyProperty; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new NoClone()); } @Override public Class beanType() { return NoClone.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code dummyProperty} property. * @return the meta-property, not null */ public final MetaProperty dummyProperty() { return dummyProperty; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -184213859: // dummyProperty return ((NoClone) bean).getDummyProperty(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -184213859: // dummyProperty ((NoClone) bean).setDummyProperty((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/NoGenEquals.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock used for test equals and final class. *

* The {@code cacheHashCode} flag is a test to ensure it is ignored. * * @author Stephen Colebourne */ @BeanDefinition(cacheHashCode = true) public final class NoGenEquals extends DirectBean { /** * The value. */ @PropertyDefinition private Object value; @Override public boolean equals(Object obj) { // should block equals generation return obj == this; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code NoGenEquals}. * @return the meta-bean, not null */ public static NoGenEquals.Meta meta() { return NoGenEquals.Meta.INSTANCE; } static { MetaBean.register(NoGenEquals.Meta.INSTANCE); } @Override public NoGenEquals.Meta metaBean() { return NoGenEquals.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property */ public Object getValue() { return value; } /** * Sets the value. * @param value the new value of the property */ public void setValue(Object value) { this.value = value; } /** * Gets the the {@code value} property. * @return the property, not null */ public Property value() { return metaBean().value().createProperty(this); } //----------------------------------------------------------------------- @Override public NoGenEquals clone() { return JodaBeanUtils.cloneAlways(this); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("NoGenEquals{"); buf.append("value").append('=').append(JodaBeanUtils.toString(getValue())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code NoGenEquals}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofReadWrite( this, "value", NoGenEquals.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new NoGenEquals()); } @Override public Class beanType() { return NoGenEquals.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((NoGenEquals) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value ((NoGenEquals) bean).setValue((Object) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/NoGenToString.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock used for test toString generation. * * @author Stephen Colebourne */ @BeanDefinition public class NoGenToString extends DirectBean { /** * The value. */ @PropertyDefinition private Object value; @Override public String toString() { return "NoGenToString"; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code NoGenToString}. * @return the meta-bean, not null */ public static NoGenToString.Meta meta() { return NoGenToString.Meta.INSTANCE; } static { MetaBean.register(NoGenToString.Meta.INSTANCE); } @Override public NoGenToString.Meta metaBean() { return NoGenToString.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the value. * @return the value of the property */ public Object getValue() { return value; } /** * Sets the value. * @param value the new value of the property */ public void setValue(Object value) { this.value = value; } /** * Gets the the {@code value} property. * @return the property, not null */ public final Property value() { return metaBean().value().createProperty(this); } //----------------------------------------------------------------------- @Override public NoGenToString clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { NoGenToString other = (NoGenToString) obj; return JodaBeanUtils.equal(this.getValue(), other.getValue()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getValue()); return hash; } //----------------------------------------------------------------------- /** * The meta-bean for {@code NoGenToString}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ private final MetaProperty value = DirectMetaProperty.ofReadWrite( this, "value", NoGenToString.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return this.value; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new NoGenToString()); } @Override public Class beanType() { return NoGenToString.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public final MetaProperty value() { return value; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((NoGenToString) bean).getValue(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value ((NoGenToString) bean).setValue((Object) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/NoProperties.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock used for testing an absence of properties. * * @author Stephen Colebourne */ @BeanDefinition public class NoProperties extends DirectBean { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code NoProperties}. * @return the meta-bean, not null */ public static NoProperties.Meta meta() { return NoProperties.Meta.INSTANCE; } static { MetaBean.register(NoProperties.Meta.INSTANCE); } @Override public NoProperties.Meta metaBean() { return NoProperties.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public NoProperties clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return true; } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("NoProperties{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { } //----------------------------------------------------------------------- /** * The meta-bean for {@code NoProperties}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null); /** * Restricted constructor. */ protected Meta() { } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new NoProperties()); } @Override public Class beanType() { return NoProperties.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/Pair.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock pair, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class Pair extends DirectBean { // extra spaces in definition /** * The first value. */ @PropertyDefinition private Object first; /** * The second value. */ @PropertyDefinition private Object second; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code Pair}. * @return the meta-bean, not null */ public static Pair.Meta meta() { return Pair.Meta.INSTANCE; } static { MetaBean.register(Pair.Meta.INSTANCE); } @Override public Pair.Meta metaBean() { return Pair.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public Object getFirst() { return first; } /** * Sets the first value. * @param first the new value of the property */ public void setFirst(Object first) { this.first = first; } /** * Gets the the {@code first} property. * @return the property, not null */ public final Property first() { return metaBean().first().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public Object getSecond() { return second; } /** * Sets the second value. * @param second the new value of the property */ public void setSecond(Object second) { this.second = second; } /** * Gets the the {@code second} property. * @return the property, not null */ public final Property second() { return metaBean().second().createProperty(this); } //----------------------------------------------------------------------- @Override public Pair clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Pair other = (Pair) obj; return JodaBeanUtils.equal(this.getFirst(), other.getFirst()) && JodaBeanUtils.equal(this.getSecond(), other.getSecond()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getFirst()); hash = hash * 31 + JodaBeanUtils.hashCode(getSecond()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("Pair{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("first").append('=').append(JodaBeanUtils.toString(getFirst())).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(getSecond())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Pair}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ private final MetaProperty first = DirectMetaProperty.ofReadWrite( this, "first", Pair.class, Object.class); /** * The meta-property for the {@code second} property. */ private final MetaProperty second = DirectMetaProperty.ofReadWrite( this, "second", Pair.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new Pair()); } @Override public Class beanType() { return Pair.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public final MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public final MetaProperty second() { return second; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((Pair) bean).getFirst(); case -906279820: // second return ((Pair) bean).getSecond(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first ((Pair) bean).setFirst((Object) newValue); return; case -906279820: // second ((Pair) bean).setSecond((Object) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/PairBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.NoSuchElementException; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.impl.BasicImmutableBeanBuilder; /** * Mock builder, used for testing. */ public final class PairBuilder extends BasicImmutableBeanBuilder { private String first; private String second; PairBuilder() { super(PairManualTopLevelBuilder.meta()); } PairBuilder(PairManualTopLevelBuilder beanToCopy) { super(PairManualTopLevelBuilder.meta()); this.first = beanToCopy.getFirst(); this.second = beanToCopy.getSecond(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName) { case "first": return first; case "second": return second; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public PairBuilder set(String propertyName, Object newValue) { switch (propertyName) { case "first": this.first = (String) newValue; break; case "second": this.second = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public PairBuilder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public PairManualTopLevelBuilder build() { return new PairManualTopLevelBuilder(first, second); } //----------------------------------------------------------------------- /** * Sets the first value. * @param first the new value * @return this, for chaining, not null */ public PairBuilder first(String first) { this.first = first; return this; } /** * Sets the second value. * @param second the new value * @return this, for chaining, not null */ public PairBuilder second(String second) { this.second = second; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("PairManualBuilder.Builder{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)); buf.append('}'); return buf.toString(); } } ================================================ FILE: src/test/java/org/joda/beans/sample/PairDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.DefaultDeserializer; /** * Mock deserializer. */ public final class PairDeserializer extends DefaultDeserializer { @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { if ("left".equals(propertyName)) { return metaBean.metaProperty("first"); } if ("right".equals(propertyName)) { return metaBean.metaProperty("second"); } return super.findMetaProperty(beanType, metaBean, propertyName); } } ================================================ FILE: src/test/java/org/joda/beans/sample/PairManualInnerBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.BasicImmutableBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock pair, used for testing. */ @BeanDefinition(builderName = "Builder") public final class PairManualInnerBuilder implements ImmutableBean { /** * The first value. */ @PropertyDefinition private final String first; /** * The second value. */ @PropertyDefinition private final String second; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code PairManualInnerBuilder}. * @return the meta-bean, not null */ public static PairManualInnerBuilder.Meta meta() { return PairManualInnerBuilder.Meta.INSTANCE; } static { MetaBean.register(PairManualInnerBuilder.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static Builder builder() { return new Builder(); } private PairManualInnerBuilder( String first, String second) { this.first = first; this.second = second; } @Override public PairManualInnerBuilder.Meta metaBean() { return PairManualInnerBuilder.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public String getFirst() { return first; } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public String getSecond() { return second; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { PairManualInnerBuilder other = (PairManualInnerBuilder) obj; return JodaBeanUtils.equal(this.first, other.first) && JodaBeanUtils.equal(this.second, other.second); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(first); hash = hash * 31 + JodaBeanUtils.hashCode(second); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("PairManualInnerBuilder{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code PairManualInnerBuilder}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ private final MetaProperty first = DirectMetaProperty.ofImmutable( this, "first", PairManualInnerBuilder.class, String.class); /** * The meta-property for the {@code second} property. */ private final MetaProperty second = DirectMetaProperty.ofImmutable( this, "second", PairManualInnerBuilder.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; } return super.metaPropertyGet(propertyName); } @Override public Builder builder() { return new Builder(); } @Override public Class beanType() { return PairManualInnerBuilder.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public MetaProperty second() { return second; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((PairManualInnerBuilder) bean).getFirst(); case -906279820: // second return ((PairManualInnerBuilder) bean).getSecond(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //-------------------------- AUTOGENERATED END -------------------------- /** * The bean-builder for {@code PairManualBuilder}. */ public static final class Builder extends BasicImmutableBeanBuilder { private String first; private String second; private Builder() { super(meta()); } private Builder(PairManualInnerBuilder beanToCopy) { super(meta()); this.first = beanToCopy.getFirst(); this.second = beanToCopy.getSecond(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName) { case "first": return first; case "second": return second; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName) { case "first": this.first = (String) newValue; break; case "second": this.second = (String) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public PairManualInnerBuilder build() { return new PairManualInnerBuilder(first, second); } //----------------------------------------------------------------------- /** * Sets the first value. * @param first the new value * @return this, for chaining, not null */ public Builder first(String first) { this.first = first; return this; } /** * Sets the second value. * @param second the new value * @return this, for chaining, not null */ public Builder second(String second) { this.second = second; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("PairManualBuilder.Builder{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)); buf.append('}'); return buf.toString(); } } } ================================================ FILE: src/test/java/org/joda/beans/sample/PairManualTopLevelBuilder.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock pair, used for testing. */ @BeanDefinition(builderName = "PairBuilder", constructorScope = "package") public final class PairManualTopLevelBuilder implements ImmutableBean { /** * The first value. */ @PropertyDefinition private final String first; /** * The second value. */ @PropertyDefinition private final String second; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code PairManualTopLevelBuilder}. * @return the meta-bean, not null */ public static PairManualTopLevelBuilder.Meta meta() { return PairManualTopLevelBuilder.Meta.INSTANCE; } static { MetaBean.register(PairManualTopLevelBuilder.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static PairBuilder builder() { return new PairBuilder(); } /** * Creates an instance. * @param first the value of the property * @param second the value of the property */ PairManualTopLevelBuilder( String first, String second) { this.first = first; this.second = second; } @Override public PairManualTopLevelBuilder.Meta metaBean() { return PairManualTopLevelBuilder.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public String getFirst() { return first; } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public String getSecond() { return second; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public PairBuilder toBuilder() { return new PairBuilder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { PairManualTopLevelBuilder other = (PairManualTopLevelBuilder) obj; return JodaBeanUtils.equal(this.first, other.first) && JodaBeanUtils.equal(this.second, other.second); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(first); hash = hash * 31 + JodaBeanUtils.hashCode(second); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("PairManualTopLevelBuilder{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code PairManualTopLevelBuilder}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ private final MetaProperty first = DirectMetaProperty.ofImmutable( this, "first", PairManualTopLevelBuilder.class, String.class); /** * The meta-property for the {@code second} property. */ private final MetaProperty second = DirectMetaProperty.ofImmutable( this, "second", PairManualTopLevelBuilder.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; } return super.metaPropertyGet(propertyName); } @Override public PairBuilder builder() { return new PairBuilder(); } @Override public Class beanType() { return PairManualTopLevelBuilder.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public MetaProperty second() { return second; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((PairManualTopLevelBuilder) bean).getFirst(); case -906279820: // second return ((PairManualTopLevelBuilder) bean).getSecond(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/Person.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.impl.flexi.FlexiBean; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition @ClassAnnotation(Address.class) public final class Person extends DirectBean implements IPerson, Serializable { // note that Serializable is on a new line /** The forename. */ @PropertyDefinition(overrideGet = true) private String forename; /** The surname. */ @PropertyDefinition(overrideGet = true, overrideSet = true) private String surname; /** The number of cars. */ @PropertyDefinition private transient int numberOfCars; @PropertyDefinition private final List
addressList = new ArrayList<>(); @PropertyDefinition private final Map otherAddressMap = new HashMap<>(); @PropertyDefinition private final List> addressesList = new ArrayList<>(); @PropertyDefinition private Address mainAddress; @PropertyDefinition @SimpleAnnotation private final FlexiBean extensions = new FlexiBean(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code Person}. * @return the meta-bean, not null */ public static Person.Meta meta() { return Person.Meta.INSTANCE; } static { MetaBean.register(Person.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; @Override public Person.Meta metaBean() { return Person.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ @Override public String getForename() { return forename; } /** * Sets the forename. * @param forename the new value of the property */ public void setForename(String forename) { this.forename = forename; } /** * Gets the the {@code forename} property. * @return the property, not null */ public Property forename() { return metaBean().forename().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ @Override public String getSurname() { return surname; } /** * Sets the surname. * @param surname the new value of the property */ @Override public void setSurname(String surname) { this.surname = surname; } /** * Gets the the {@code surname} property. * @return the property, not null */ public Property surname() { return metaBean().surname().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the number of cars. * @return the value of the property */ public int getNumberOfCars() { return numberOfCars; } /** * Sets the number of cars. * @param numberOfCars the new value of the property */ public void setNumberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; } /** * Gets the the {@code numberOfCars} property. * @return the property, not null */ public Property numberOfCars() { return metaBean().numberOfCars().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressList. * @return the value of the property, not null */ public List
getAddressList() { return addressList; } /** * Sets the addressList. * @param addressList the new value of the property, not null */ public void setAddressList(List
addressList) { JodaBeanUtils.notNull(addressList, "addressList"); this.addressList.clear(); this.addressList.addAll(addressList); } /** * Gets the the {@code addressList} property. * @return the property, not null */ public Property> addressList() { return metaBean().addressList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the otherAddressMap. * @return the value of the property, not null */ public Map getOtherAddressMap() { return otherAddressMap; } /** * Sets the otherAddressMap. * @param otherAddressMap the new value of the property, not null */ public void setOtherAddressMap(Map otherAddressMap) { JodaBeanUtils.notNull(otherAddressMap, "otherAddressMap"); this.otherAddressMap.clear(); this.otherAddressMap.putAll(otherAddressMap); } /** * Gets the the {@code otherAddressMap} property. * @return the property, not null */ public Property> otherAddressMap() { return metaBean().otherAddressMap().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressesList. * @return the value of the property, not null */ public List> getAddressesList() { return addressesList; } /** * Sets the addressesList. * @param addressesList the new value of the property, not null */ public void setAddressesList(List> addressesList) { JodaBeanUtils.notNull(addressesList, "addressesList"); this.addressesList.clear(); this.addressesList.addAll(addressesList); } /** * Gets the the {@code addressesList} property. * @return the property, not null */ public Property>> addressesList() { return metaBean().addressesList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the mainAddress. * @return the value of the property */ public Address getMainAddress() { return mainAddress; } /** * Sets the mainAddress. * @param mainAddress the new value of the property */ public void setMainAddress(Address mainAddress) { this.mainAddress = mainAddress; } /** * Gets the the {@code mainAddress} property. * @return the property, not null */ public Property
mainAddress() { return metaBean().mainAddress().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the extensions. * @return the value of the property, not null */ public FlexiBean getExtensions() { return extensions; } /** * Sets the extensions. * @param extensions the new value of the property, not null */ public void setExtensions(FlexiBean extensions) { JodaBeanUtils.notNull(extensions, "extensions"); this.extensions.clear(); this.extensions.putAll(extensions); } /** * Gets the the {@code extensions} property. * @return the property, not null */ public Property extensions() { return metaBean().extensions().createProperty(this); } //----------------------------------------------------------------------- @Override public Person clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Person other = (Person) obj; return JodaBeanUtils.equal(this.getForename(), other.getForename()) && JodaBeanUtils.equal(this.getSurname(), other.getSurname()) && (this.getNumberOfCars() == other.getNumberOfCars()) && JodaBeanUtils.equal(this.getAddressList(), other.getAddressList()) && JodaBeanUtils.equal(this.getOtherAddressMap(), other.getOtherAddressMap()) && JodaBeanUtils.equal(this.getAddressesList(), other.getAddressesList()) && JodaBeanUtils.equal(this.getMainAddress(), other.getMainAddress()) && JodaBeanUtils.equal(this.getExtensions(), other.getExtensions()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getForename()); hash = hash * 31 + JodaBeanUtils.hashCode(getSurname()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberOfCars()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressList()); hash = hash * 31 + JodaBeanUtils.hashCode(getOtherAddressMap()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressesList()); hash = hash * 31 + JodaBeanUtils.hashCode(getMainAddress()); hash = hash * 31 + JodaBeanUtils.hashCode(getExtensions()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("Person{"); buf.append("forename").append('=').append(JodaBeanUtils.toString(getForename())).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(getSurname())).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(getNumberOfCars())).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(getAddressList())).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(getOtherAddressMap())).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(getAddressesList())).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(getMainAddress())).append(',').append(' '); buf.append("extensions").append('=').append(JodaBeanUtils.toString(getExtensions())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Person}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofReadWrite( this, "forename", Person.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofReadWrite( this, "surname", Person.class, String.class); /** * The meta-property for the {@code numberOfCars} property. */ private final MetaProperty numberOfCars = DirectMetaProperty.ofReadWrite( this, "numberOfCars", Person.class, Integer.TYPE); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofReadWrite( this, "addressList", Person.class, (Class) List.class); /** * The meta-property for the {@code otherAddressMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> otherAddressMap = DirectMetaProperty.ofReadWrite( this, "otherAddressMap", Person.class, (Class) Map.class); /** * The meta-property for the {@code addressesList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> addressesList = DirectMetaProperty.ofReadWrite( this, "addressesList", Person.class, (Class) List.class); /** * The meta-property for the {@code mainAddress} property. */ private final MetaProperty
mainAddress = DirectMetaProperty.ofReadWrite( this, "mainAddress", Person.class, Address.class); /** * The meta-property for the {@code extensions} property. */ private final MetaProperty extensions = DirectMetaProperty.ofReadWrite( this, "extensions", Person.class, FlexiBean.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "numberOfCars", "addressList", "otherAddressMap", "addressesList", "mainAddress", "extensions"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; case -1809421292: // extensions return this.extensions; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new Person()); } @Override public Class beanType() { return Person.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public MetaProperty surname() { return surname; } /** * The meta-property for the {@code numberOfCars} property. * @return the meta-property, not null */ public MetaProperty numberOfCars() { return numberOfCars; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public MetaProperty> addressList() { return addressList; } /** * The meta-property for the {@code otherAddressMap} property. * @return the meta-property, not null */ public MetaProperty> otherAddressMap() { return otherAddressMap; } /** * The meta-property for the {@code addressesList} property. * @return the meta-property, not null */ public MetaProperty>> addressesList() { return addressesList; } /** * The meta-property for the {@code mainAddress} property. * @return the meta-property, not null */ public MetaProperty
mainAddress() { return mainAddress; } /** * The meta-property for the {@code extensions} property. * @return the meta-property, not null */ public MetaProperty extensions() { return extensions; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((Person) bean).getForename(); case -1852993317: // surname return ((Person) bean).getSurname(); case 926656063: // numberOfCars return ((Person) bean).getNumberOfCars(); case -1377524046: // addressList return ((Person) bean).getAddressList(); case 1368089592: // otherAddressMap return ((Person) bean).getOtherAddressMap(); case -226885792: // addressesList return ((Person) bean).getAddressesList(); case -2032731141: // mainAddress return ((Person) bean).getMainAddress(); case -1809421292: // extensions return ((Person) bean).getExtensions(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename ((Person) bean).setForename((String) newValue); return; case -1852993317: // surname ((Person) bean).setSurname((String) newValue); return; case 926656063: // numberOfCars ((Person) bean).setNumberOfCars((Integer) newValue); return; case -1377524046: // addressList ((Person) bean).setAddressList((List
) newValue); return; case 1368089592: // otherAddressMap ((Person) bean).setOtherAddressMap((Map) newValue); return; case -226885792: // addressesList ((Person) bean).setAddressesList((List>) newValue); return; case -2032731141: // mainAddress ((Person) bean).setMainAddress((Address) newValue); return; case -1809421292: // extensions ((Person) bean).setExtensions((FlexiBean) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((Person) bean).addressList, "addressList"); JodaBeanUtils.notNull(((Person) bean).otherAddressMap, "otherAddressMap"); JodaBeanUtils.notNull(((Person) bean).addressesList, "addressesList"); JodaBeanUtils.notNull(((Person) bean).extensions, "extensions"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/PersonDocumentation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class PersonDocumentation extends Documentation { /** The name. */ @PropertyDefinition private String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code PersonDocumentation}. * @return the meta-bean, not null */ public static PersonDocumentation.Meta meta() { return PersonDocumentation.Meta.INSTANCE; } static { MetaBean.register(PersonDocumentation.Meta.INSTANCE); } @Override public PersonDocumentation.Meta metaBean() { return PersonDocumentation.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property */ public void setName(String name) { this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- @Override public PersonDocumentation clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { PersonDocumentation other = (PersonDocumentation) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("PersonDocumentation{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code PersonDocumentation}. */ public static class Meta extends Documentation.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", PersonDocumentation.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "name"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new PersonDocumentation()); } @Override public Class beanType() { return PersonDocumentation.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((PersonDocumentation) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((PersonDocumentation) bean).setName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/PrimitiveBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class PrimitiveBean extends DirectBean { @PropertyDefinition private long valueLong; @PropertyDefinition private int valueInt; @PropertyDefinition private short valueShort; @PropertyDefinition private byte valueByte; @PropertyDefinition private double valueDouble; @PropertyDefinition private float valueFloat; @PropertyDefinition private char valueChar; @PropertyDefinition private boolean valueBoolean; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code PrimitiveBean}. * @return the meta-bean, not null */ public static PrimitiveBean.Meta meta() { return PrimitiveBean.Meta.INSTANCE; } static { MetaBean.register(PrimitiveBean.Meta.INSTANCE); } @Override public PrimitiveBean.Meta metaBean() { return PrimitiveBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the valueLong. * @return the value of the property */ public long getValueLong() { return valueLong; } /** * Sets the valueLong. * @param valueLong the new value of the property */ public void setValueLong(long valueLong) { this.valueLong = valueLong; } /** * Gets the the {@code valueLong} property. * @return the property, not null */ public final Property valueLong() { return metaBean().valueLong().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueInt. * @return the value of the property */ public int getValueInt() { return valueInt; } /** * Sets the valueInt. * @param valueInt the new value of the property */ public void setValueInt(int valueInt) { this.valueInt = valueInt; } /** * Gets the the {@code valueInt} property. * @return the property, not null */ public final Property valueInt() { return metaBean().valueInt().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueShort. * @return the value of the property */ public short getValueShort() { return valueShort; } /** * Sets the valueShort. * @param valueShort the new value of the property */ public void setValueShort(short valueShort) { this.valueShort = valueShort; } /** * Gets the the {@code valueShort} property. * @return the property, not null */ public final Property valueShort() { return metaBean().valueShort().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueByte. * @return the value of the property */ public byte getValueByte() { return valueByte; } /** * Sets the valueByte. * @param valueByte the new value of the property */ public void setValueByte(byte valueByte) { this.valueByte = valueByte; } /** * Gets the the {@code valueByte} property. * @return the property, not null */ public final Property valueByte() { return metaBean().valueByte().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueDouble. * @return the value of the property */ public double getValueDouble() { return valueDouble; } /** * Sets the valueDouble. * @param valueDouble the new value of the property */ public void setValueDouble(double valueDouble) { this.valueDouble = valueDouble; } /** * Gets the the {@code valueDouble} property. * @return the property, not null */ public final Property valueDouble() { return metaBean().valueDouble().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueFloat. * @return the value of the property */ public float getValueFloat() { return valueFloat; } /** * Sets the valueFloat. * @param valueFloat the new value of the property */ public void setValueFloat(float valueFloat) { this.valueFloat = valueFloat; } /** * Gets the the {@code valueFloat} property. * @return the property, not null */ public final Property valueFloat() { return metaBean().valueFloat().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueChar. * @return the value of the property */ public char getValueChar() { return valueChar; } /** * Sets the valueChar. * @param valueChar the new value of the property */ public void setValueChar(char valueChar) { this.valueChar = valueChar; } /** * Gets the the {@code valueChar} property. * @return the property, not null */ public final Property valueChar() { return metaBean().valueChar().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the valueBoolean. * @return the value of the property */ public boolean isValueBoolean() { return valueBoolean; } /** * Sets the valueBoolean. * @param valueBoolean the new value of the property */ public void setValueBoolean(boolean valueBoolean) { this.valueBoolean = valueBoolean; } /** * Gets the the {@code valueBoolean} property. * @return the property, not null */ public final Property valueBoolean() { return metaBean().valueBoolean().createProperty(this); } //----------------------------------------------------------------------- @Override public PrimitiveBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { PrimitiveBean other = (PrimitiveBean) obj; return (this.getValueLong() == other.getValueLong()) && (this.getValueInt() == other.getValueInt()) && (this.getValueShort() == other.getValueShort()) && (this.getValueByte() == other.getValueByte()) && JodaBeanUtils.equal(this.getValueDouble(), other.getValueDouble()) && JodaBeanUtils.equal(this.getValueFloat(), other.getValueFloat()) && (this.getValueChar() == other.getValueChar()) && (this.isValueBoolean() == other.isValueBoolean()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getValueLong()); hash = hash * 31 + JodaBeanUtils.hashCode(getValueInt()); hash = hash * 31 + JodaBeanUtils.hashCode(getValueShort()); hash = hash * 31 + JodaBeanUtils.hashCode(getValueByte()); hash = hash * 31 + JodaBeanUtils.hashCode(getValueDouble()); hash = hash * 31 + JodaBeanUtils.hashCode(getValueFloat()); hash = hash * 31 + JodaBeanUtils.hashCode(getValueChar()); hash = hash * 31 + JodaBeanUtils.hashCode(isValueBoolean()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("PrimitiveBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("valueLong").append('=').append(JodaBeanUtils.toString(getValueLong())).append(',').append(' '); buf.append("valueInt").append('=').append(JodaBeanUtils.toString(getValueInt())).append(',').append(' '); buf.append("valueShort").append('=').append(JodaBeanUtils.toString(getValueShort())).append(',').append(' '); buf.append("valueByte").append('=').append(JodaBeanUtils.toString(getValueByte())).append(',').append(' '); buf.append("valueDouble").append('=').append(JodaBeanUtils.toString(getValueDouble())).append(',').append(' '); buf.append("valueFloat").append('=').append(JodaBeanUtils.toString(getValueFloat())).append(',').append(' '); buf.append("valueChar").append('=').append(JodaBeanUtils.toString(getValueChar())).append(',').append(' '); buf.append("valueBoolean").append('=').append(JodaBeanUtils.toString(isValueBoolean())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code PrimitiveBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code valueLong} property. */ private final MetaProperty valueLong = DirectMetaProperty.ofReadWrite( this, "valueLong", PrimitiveBean.class, Long.TYPE); /** * The meta-property for the {@code valueInt} property. */ private final MetaProperty valueInt = DirectMetaProperty.ofReadWrite( this, "valueInt", PrimitiveBean.class, Integer.TYPE); /** * The meta-property for the {@code valueShort} property. */ private final MetaProperty valueShort = DirectMetaProperty.ofReadWrite( this, "valueShort", PrimitiveBean.class, Short.TYPE); /** * The meta-property for the {@code valueByte} property. */ private final MetaProperty valueByte = DirectMetaProperty.ofReadWrite( this, "valueByte", PrimitiveBean.class, Byte.TYPE); /** * The meta-property for the {@code valueDouble} property. */ private final MetaProperty valueDouble = DirectMetaProperty.ofReadWrite( this, "valueDouble", PrimitiveBean.class, Double.TYPE); /** * The meta-property for the {@code valueFloat} property. */ private final MetaProperty valueFloat = DirectMetaProperty.ofReadWrite( this, "valueFloat", PrimitiveBean.class, Float.TYPE); /** * The meta-property for the {@code valueChar} property. */ private final MetaProperty valueChar = DirectMetaProperty.ofReadWrite( this, "valueChar", PrimitiveBean.class, Character.TYPE); /** * The meta-property for the {@code valueBoolean} property. */ private final MetaProperty valueBoolean = DirectMetaProperty.ofReadWrite( this, "valueBoolean", PrimitiveBean.class, Boolean.TYPE); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "valueLong", "valueInt", "valueShort", "valueByte", "valueDouble", "valueFloat", "valueChar", "valueBoolean"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -765940851: // valueLong return this.valueLong; case -1410184002: // valueInt return this.valueInt; case 2031894923: // valueShort return this.valueShort; case -766228967: // valueByte return this.valueByte; case -1858576222: // valueDouble return this.valueDouble; case 2020007787: // valueFloat return this.valueFloat; case -766216089: // valueChar return this.valueChar; case 733421943: // valueBoolean return this.valueBoolean; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new PrimitiveBean()); } @Override public Class beanType() { return PrimitiveBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code valueLong} property. * @return the meta-property, not null */ public final MetaProperty valueLong() { return valueLong; } /** * The meta-property for the {@code valueInt} property. * @return the meta-property, not null */ public final MetaProperty valueInt() { return valueInt; } /** * The meta-property for the {@code valueShort} property. * @return the meta-property, not null */ public final MetaProperty valueShort() { return valueShort; } /** * The meta-property for the {@code valueByte} property. * @return the meta-property, not null */ public final MetaProperty valueByte() { return valueByte; } /** * The meta-property for the {@code valueDouble} property. * @return the meta-property, not null */ public final MetaProperty valueDouble() { return valueDouble; } /** * The meta-property for the {@code valueFloat} property. * @return the meta-property, not null */ public final MetaProperty valueFloat() { return valueFloat; } /** * The meta-property for the {@code valueChar} property. * @return the meta-property, not null */ public final MetaProperty valueChar() { return valueChar; } /** * The meta-property for the {@code valueBoolean} property. * @return the meta-property, not null */ public final MetaProperty valueBoolean() { return valueBoolean; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -765940851: // valueLong return ((PrimitiveBean) bean).getValueLong(); case -1410184002: // valueInt return ((PrimitiveBean) bean).getValueInt(); case 2031894923: // valueShort return ((PrimitiveBean) bean).getValueShort(); case -766228967: // valueByte return ((PrimitiveBean) bean).getValueByte(); case -1858576222: // valueDouble return ((PrimitiveBean) bean).getValueDouble(); case 2020007787: // valueFloat return ((PrimitiveBean) bean).getValueFloat(); case -766216089: // valueChar return ((PrimitiveBean) bean).getValueChar(); case 733421943: // valueBoolean return ((PrimitiveBean) bean).isValueBoolean(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -765940851: // valueLong ((PrimitiveBean) bean).setValueLong((Long) newValue); return; case -1410184002: // valueInt ((PrimitiveBean) bean).setValueInt((Integer) newValue); return; case 2031894923: // valueShort ((PrimitiveBean) bean).setValueShort((Short) newValue); return; case -766228967: // valueByte ((PrimitiveBean) bean).setValueByte((Byte) newValue); return; case -1858576222: // valueDouble ((PrimitiveBean) bean).setValueDouble((Double) newValue); return; case 2020007787: // valueFloat ((PrimitiveBean) bean).setValueFloat((Float) newValue); return; case -766216089: // valueChar ((PrimitiveBean) bean).setValueChar((Character) newValue); return; case 733421943: // valueBoolean ((PrimitiveBean) bean).setValueBoolean((Boolean) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/PropertyDefBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.Lists; /** * Mock immutable person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class PropertyDefBean implements Bean { @PropertyDefinition(type = "CharSequence", set = "$value.toString()") private String stringAsCharSequence; @PropertyDefinition(type = "Integer") private int intAsInteger; @PropertyDefinition(type = "Collection<>", set = "new ArrayList<>($value)") private List
listCopyOfCollection = new ArrayList<>(); @PropertyDefinition private final ArrayList
arrayListSmart = new ArrayList<>(); @PropertyDefinition(type = "") private final ArrayList
arrayListExposed = new ArrayList<>(); @PropertyDefinition(type = "Collection<>") private final ArrayList
arrayListAsCollection = new ArrayList<>(); @PropertyDefinition private final ArrayList
arrayList = new ArrayList<>(); @PropertyDefinition(type = "Iterable<>", set = "$field = Lists.newArrayList($value)") private List
listAsIterable = new ArrayList<>(); @PropertyDefinition(type = "Iterable", set = "Lists.newArrayList($value)") private List
listAsIterableNoField = new ArrayList<>(); //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code PropertyDefBean}. * @return the meta-bean, not null */ public static PropertyDefBean.Meta meta() { return PropertyDefBean.Meta.INSTANCE; } static { MetaBean.register(PropertyDefBean.Meta.INSTANCE); } @Override public PropertyDefBean.Meta metaBean() { return PropertyDefBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the stringAsCharSequence. * @return the value of the property */ public CharSequence getStringAsCharSequence() { return stringAsCharSequence; } /** * Sets the stringAsCharSequence. * @param stringAsCharSequence the new value of the property */ public void setStringAsCharSequence(CharSequence stringAsCharSequence) { this.stringAsCharSequence = stringAsCharSequence.toString(); } /** * Gets the the {@code stringAsCharSequence} property. * @return the property, not null */ public Property stringAsCharSequence() { return metaBean().stringAsCharSequence().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the intAsInteger. * @return the value of the property */ public Integer getIntAsInteger() { return intAsInteger; } /** * Sets the intAsInteger. * @param intAsInteger the new value of the property */ public void setIntAsInteger(Integer intAsInteger) { this.intAsInteger = intAsInteger; } /** * Gets the the {@code intAsInteger} property. * @return the property, not null */ public Property intAsInteger() { return metaBean().intAsInteger().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the listCopyOfCollection. * @return the value of the property */ public Collection
getListCopyOfCollection() { return listCopyOfCollection; } /** * Sets the listCopyOfCollection. * @param listCopyOfCollection the new value of the property */ public void setListCopyOfCollection(Collection
listCopyOfCollection) { this.listCopyOfCollection = new ArrayList<>(listCopyOfCollection); } /** * Gets the the {@code listCopyOfCollection} property. * @return the property, not null */ public Property> listCopyOfCollection() { return metaBean().listCopyOfCollection().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the arrayListSmart. * @return the value of the property, not null */ public ArrayList
getArrayListSmart() { return arrayListSmart; } /** * Sets the arrayListSmart. * @param arrayListSmart the new value of the property, not null */ public void setArrayListSmart(ArrayList
arrayListSmart) { JodaBeanUtils.notNull(arrayListSmart, "arrayListSmart"); this.arrayListSmart.clear(); this.arrayListSmart.addAll(arrayListSmart); } /** * Gets the the {@code arrayListSmart} property. * @return the property, not null */ public Property> arrayListSmart() { return metaBean().arrayListSmart().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the arrayListExposed. * @return the value of the property, not null */ public ArrayList
getArrayListExposed() { return arrayListExposed; } /** * Sets the arrayListExposed. * @param arrayListExposed the new value of the property, not null */ public void setArrayListExposed(ArrayList
arrayListExposed) { JodaBeanUtils.notNull(arrayListExposed, "arrayListExposed"); this.arrayListExposed.clear(); this.arrayListExposed.addAll(arrayListExposed); } /** * Gets the the {@code arrayListExposed} property. * @return the property, not null */ public Property> arrayListExposed() { return metaBean().arrayListExposed().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the arrayListAsCollection. * @return the value of the property, not null */ public Collection
getArrayListAsCollection() { return arrayListAsCollection; } /** * Sets the arrayListAsCollection. * @param arrayListAsCollection the new value of the property, not null */ public void setArrayListAsCollection(Collection
arrayListAsCollection) { JodaBeanUtils.notNull(arrayListAsCollection, "arrayListAsCollection"); this.arrayListAsCollection.clear(); this.arrayListAsCollection.addAll(arrayListAsCollection); } /** * Gets the the {@code arrayListAsCollection} property. * @return the property, not null */ public Property> arrayListAsCollection() { return metaBean().arrayListAsCollection().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the arrayList. * @return the value of the property, not null */ public ArrayList
getArrayList() { return arrayList; } /** * Sets the arrayList. * @param arrayList the new value of the property, not null */ public void setArrayList(ArrayList
arrayList) { JodaBeanUtils.notNull(arrayList, "arrayList"); this.arrayList.clear(); this.arrayList.addAll(arrayList); } /** * Gets the the {@code arrayList} property. * @return the property, not null */ public Property> arrayList() { return metaBean().arrayList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the listAsIterable. * @return the value of the property */ public Iterable
getListAsIterable() { return listAsIterable; } /** * Sets the listAsIterable. * @param listAsIterable the new value of the property */ public void setListAsIterable(Iterable
listAsIterable) { this.listAsIterable = Lists.newArrayList(listAsIterable); } /** * Gets the the {@code listAsIterable} property. * @return the property, not null */ public Property> listAsIterable() { return metaBean().listAsIterable().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the listAsIterableNoField. * @return the value of the property */ public Iterable
getListAsIterableNoField() { return listAsIterableNoField; } /** * Sets the listAsIterableNoField. * @param listAsIterableNoField the new value of the property */ public void setListAsIterableNoField(Iterable
listAsIterableNoField) { this.listAsIterableNoField = Lists.newArrayList(listAsIterableNoField); } /** * Gets the the {@code listAsIterableNoField} property. * @return the property, not null */ public Property> listAsIterableNoField() { return metaBean().listAsIterableNoField().createProperty(this); } //----------------------------------------------------------------------- @Override public PropertyDefBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { PropertyDefBean other = (PropertyDefBean) obj; return JodaBeanUtils.equal(this.getStringAsCharSequence(), other.getStringAsCharSequence()) && JodaBeanUtils.equal(this.getIntAsInteger(), other.getIntAsInteger()) && JodaBeanUtils.equal(this.getListCopyOfCollection(), other.getListCopyOfCollection()) && JodaBeanUtils.equal(this.getArrayListSmart(), other.getArrayListSmart()) && JodaBeanUtils.equal(this.getArrayListExposed(), other.getArrayListExposed()) && JodaBeanUtils.equal(this.getArrayListAsCollection(), other.getArrayListAsCollection()) && JodaBeanUtils.equal(this.getArrayList(), other.getArrayList()) && JodaBeanUtils.equal(this.getListAsIterable(), other.getListAsIterable()) && JodaBeanUtils.equal(this.getListAsIterableNoField(), other.getListAsIterableNoField()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getStringAsCharSequence()); hash = hash * 31 + JodaBeanUtils.hashCode(getIntAsInteger()); hash = hash * 31 + JodaBeanUtils.hashCode(getListCopyOfCollection()); hash = hash * 31 + JodaBeanUtils.hashCode(getArrayListSmart()); hash = hash * 31 + JodaBeanUtils.hashCode(getArrayListExposed()); hash = hash * 31 + JodaBeanUtils.hashCode(getArrayListAsCollection()); hash = hash * 31 + JodaBeanUtils.hashCode(getArrayList()); hash = hash * 31 + JodaBeanUtils.hashCode(getListAsIterable()); hash = hash * 31 + JodaBeanUtils.hashCode(getListAsIterableNoField()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("PropertyDefBean{"); buf.append("stringAsCharSequence").append('=').append(JodaBeanUtils.toString(getStringAsCharSequence())).append(',').append(' '); buf.append("intAsInteger").append('=').append(JodaBeanUtils.toString(getIntAsInteger())).append(',').append(' '); buf.append("listCopyOfCollection").append('=').append(JodaBeanUtils.toString(getListCopyOfCollection())).append(',').append(' '); buf.append("arrayListSmart").append('=').append(JodaBeanUtils.toString(getArrayListSmart())).append(',').append(' '); buf.append("arrayListExposed").append('=').append(JodaBeanUtils.toString(getArrayListExposed())).append(',').append(' '); buf.append("arrayListAsCollection").append('=').append(JodaBeanUtils.toString(getArrayListAsCollection())).append(',').append(' '); buf.append("arrayList").append('=').append(JodaBeanUtils.toString(getArrayList())).append(',').append(' '); buf.append("listAsIterable").append('=').append(JodaBeanUtils.toString(getListAsIterable())).append(',').append(' '); buf.append("listAsIterableNoField").append('=').append(JodaBeanUtils.toString(getListAsIterableNoField())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code PropertyDefBean}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code stringAsCharSequence} property. */ private final MetaProperty stringAsCharSequence = DirectMetaProperty.ofReadWrite( this, "stringAsCharSequence", PropertyDefBean.class, CharSequence.class); /** * The meta-property for the {@code intAsInteger} property. */ private final MetaProperty intAsInteger = DirectMetaProperty.ofReadWrite( this, "intAsInteger", PropertyDefBean.class, Integer.class); /** * The meta-property for the {@code listCopyOfCollection} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listCopyOfCollection = DirectMetaProperty.ofReadWrite( this, "listCopyOfCollection", PropertyDefBean.class, (Class) Collection.class); /** * The meta-property for the {@code arrayListSmart} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> arrayListSmart = DirectMetaProperty.ofReadWrite( this, "arrayListSmart", PropertyDefBean.class, (Class) ArrayList.class); /** * The meta-property for the {@code arrayListExposed} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> arrayListExposed = DirectMetaProperty.ofReadWrite( this, "arrayListExposed", PropertyDefBean.class, (Class) ArrayList.class); /** * The meta-property for the {@code arrayListAsCollection} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> arrayListAsCollection = DirectMetaProperty.ofReadWrite( this, "arrayListAsCollection", PropertyDefBean.class, (Class) Collection.class); /** * The meta-property for the {@code arrayList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> arrayList = DirectMetaProperty.ofReadWrite( this, "arrayList", PropertyDefBean.class, (Class) ArrayList.class); /** * The meta-property for the {@code listAsIterable} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listAsIterable = DirectMetaProperty.ofReadWrite( this, "listAsIterable", PropertyDefBean.class, (Class) Iterable.class); /** * The meta-property for the {@code listAsIterableNoField} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> listAsIterableNoField = DirectMetaProperty.ofReadWrite( this, "listAsIterableNoField", PropertyDefBean.class, (Class) Iterable.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "stringAsCharSequence", "intAsInteger", "listCopyOfCollection", "arrayListSmart", "arrayListExposed", "arrayListAsCollection", "arrayList", "listAsIterable", "listAsIterableNoField"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -626353926: // stringAsCharSequence return this.stringAsCharSequence; case -86092419: // intAsInteger return this.intAsInteger; case 1005120680: // listCopyOfCollection return this.listCopyOfCollection; case 1202448754: // arrayListSmart return this.arrayListSmart; case 995586697: // arrayListExposed return this.arrayListExposed; case 1604480167: // arrayListAsCollection return this.arrayListAsCollection; case -1425161577: // arrayList return this.arrayList; case -176766462: // listAsIterable return this.listAsIterable; case 1831404375: // listAsIterableNoField return this.listAsIterableNoField; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new PropertyDefBean()); } @Override public Class beanType() { return PropertyDefBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code stringAsCharSequence} property. * @return the meta-property, not null */ public MetaProperty stringAsCharSequence() { return stringAsCharSequence; } /** * The meta-property for the {@code intAsInteger} property. * @return the meta-property, not null */ public MetaProperty intAsInteger() { return intAsInteger; } /** * The meta-property for the {@code listCopyOfCollection} property. * @return the meta-property, not null */ public MetaProperty> listCopyOfCollection() { return listCopyOfCollection; } /** * The meta-property for the {@code arrayListSmart} property. * @return the meta-property, not null */ public MetaProperty> arrayListSmart() { return arrayListSmart; } /** * The meta-property for the {@code arrayListExposed} property. * @return the meta-property, not null */ public MetaProperty> arrayListExposed() { return arrayListExposed; } /** * The meta-property for the {@code arrayListAsCollection} property. * @return the meta-property, not null */ public MetaProperty> arrayListAsCollection() { return arrayListAsCollection; } /** * The meta-property for the {@code arrayList} property. * @return the meta-property, not null */ public MetaProperty> arrayList() { return arrayList; } /** * The meta-property for the {@code listAsIterable} property. * @return the meta-property, not null */ public MetaProperty> listAsIterable() { return listAsIterable; } /** * The meta-property for the {@code listAsIterableNoField} property. * @return the meta-property, not null */ public MetaProperty> listAsIterableNoField() { return listAsIterableNoField; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -626353926: // stringAsCharSequence return ((PropertyDefBean) bean).getStringAsCharSequence(); case -86092419: // intAsInteger return ((PropertyDefBean) bean).getIntAsInteger(); case 1005120680: // listCopyOfCollection return ((PropertyDefBean) bean).getListCopyOfCollection(); case 1202448754: // arrayListSmart return ((PropertyDefBean) bean).getArrayListSmart(); case 995586697: // arrayListExposed return ((PropertyDefBean) bean).getArrayListExposed(); case 1604480167: // arrayListAsCollection return ((PropertyDefBean) bean).getArrayListAsCollection(); case -1425161577: // arrayList return ((PropertyDefBean) bean).getArrayList(); case -176766462: // listAsIterable return ((PropertyDefBean) bean).getListAsIterable(); case 1831404375: // listAsIterableNoField return ((PropertyDefBean) bean).getListAsIterableNoField(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -626353926: // stringAsCharSequence ((PropertyDefBean) bean).setStringAsCharSequence((CharSequence) newValue); return; case -86092419: // intAsInteger ((PropertyDefBean) bean).setIntAsInteger((Integer) newValue); return; case 1005120680: // listCopyOfCollection ((PropertyDefBean) bean).setListCopyOfCollection((Collection
) newValue); return; case 1202448754: // arrayListSmart ((PropertyDefBean) bean).setArrayListSmart((ArrayList
) newValue); return; case 995586697: // arrayListExposed ((PropertyDefBean) bean).setArrayListExposed((ArrayList
) newValue); return; case 1604480167: // arrayListAsCollection ((PropertyDefBean) bean).setArrayListAsCollection((Collection
) newValue); return; case -1425161577: // arrayList ((PropertyDefBean) bean).setArrayList((ArrayList
) newValue); return; case -176766462: // listAsIterable ((PropertyDefBean) bean).setListAsIterable((Iterable
) newValue); return; case 1831404375: // listAsIterableNoField ((PropertyDefBean) bean).setListAsIterableNoField((Iterable
) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((PropertyDefBean) bean).arrayListSmart, "arrayListSmart"); JodaBeanUtils.notNull(((PropertyDefBean) bean).arrayListExposed, "arrayListExposed"); JodaBeanUtils.notNull(((PropertyDefBean) bean).arrayListAsCollection, "arrayListAsCollection"); JodaBeanUtils.notNull(((PropertyDefBean) bean).arrayList, "arrayList"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/RWOnlyBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.DerivedProperty; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock used for test equals. * * @author Stephen Colebourne */ @BeanDefinition public class RWOnlyBean extends DirectBean { /** * The read only property. */ @PropertyDefinition(set = "") private Object ro = null; // trailing comment /** * The write only property. */ @PropertyDefinition(get = "") private Object wo; // trailing comment /** * The final read only property. */ @PropertyDefinition private final Object fin; /** * The private get/set property. */ @PropertyDefinition(get = "private", set = "private") private String priv; /** * The package-scoped get/set property. */ @PropertyDefinition(get = "package", set = "package") private String pkg; /** * The protected get/set property. */ @PropertyDefinition(get = "protected", set = "protected") private String prot; /** * The field-based get/set property. */ @PropertyDefinition(get = "field", set = "field") private String field; public RWOnlyBean() { fin = ""; } /** * A manual get property, no set. */ @PropertyDefinition(get = "manual", set = "") private String manualGet; public String getManualGet() { return "goo"; } /** * Gets the value of a derived property. * * @return derived */ @DerivedProperty public String getDerived() { return "drv"; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code RWOnlyBean}. * @return the meta-bean, not null */ public static RWOnlyBean.Meta meta() { return RWOnlyBean.Meta.INSTANCE; } static { MetaBean.register(RWOnlyBean.Meta.INSTANCE); } @Override public RWOnlyBean.Meta metaBean() { return RWOnlyBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the read only property. * @return the value of the property */ public Object getRo() { return ro; } /** * Gets the the {@code ro} property. * @return the property, not null */ public final Property ro() { return metaBean().ro().createProperty(this); } //----------------------------------------------------------------------- /** * Sets the write only property. * @param wo the new value of the property */ public void setWo(Object wo) { this.wo = wo; } /** * Gets the the {@code wo} property. * @return the property, not null */ public final Property wo() { return metaBean().wo().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the final read only property. * @return the value of the property */ public Object getFin() { return fin; } /** * Gets the the {@code fin} property. * @return the property, not null */ public final Property fin() { return metaBean().fin().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the private get/set property. * @return the value of the property */ private String getPriv() { return priv; } /** * Sets the private get/set property. * @param priv the new value of the property */ private void setPriv(String priv) { this.priv = priv; } /** * Gets the the {@code priv} property. * @return the property, not null */ public final Property priv() { return metaBean().priv().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the package-scoped get/set property. * @return the value of the property */ String getPkg() { return pkg; } /** * Sets the package-scoped get/set property. * @param pkg the new value of the property */ void setPkg(String pkg) { this.pkg = pkg; } /** * Gets the the {@code pkg} property. * @return the property, not null */ public final Property pkg() { return metaBean().pkg().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the protected get/set property. * @return the value of the property */ protected String getProt() { return prot; } /** * Sets the protected get/set property. * @param prot the new value of the property */ protected void setProt(String prot) { this.prot = prot; } /** * Gets the the {@code prot} property. * @return the property, not null */ public final Property prot() { return metaBean().prot().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the the {@code field} property. * @return the property, not null */ public final Property field() { return metaBean().field().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the the {@code manualGet} property. * @return the property, not null */ public final Property manualGet() { return metaBean().manualGet().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the the {@code derived} property. * * @return the property, not null */ public final Property derived() { return metaBean().derived().createProperty(this); } //----------------------------------------------------------------------- @Override public RWOnlyBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { RWOnlyBean other = (RWOnlyBean) obj; return JodaBeanUtils.equal(this.getRo(), other.getRo()) && JodaBeanUtils.equal(this.wo, other.wo) && JodaBeanUtils.equal(this.getFin(), other.getFin()) && JodaBeanUtils.equal(this.getPriv(), other.getPriv()) && JodaBeanUtils.equal(this.getPkg(), other.getPkg()) && JodaBeanUtils.equal(this.getProt(), other.getProt()) && JodaBeanUtils.equal(this.field, other.field) && JodaBeanUtils.equal(this.getManualGet(), other.getManualGet()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getRo()); hash = hash * 31 + JodaBeanUtils.hashCode(wo); hash = hash * 31 + JodaBeanUtils.hashCode(getFin()); hash = hash * 31 + JodaBeanUtils.hashCode(getPriv()); hash = hash * 31 + JodaBeanUtils.hashCode(getPkg()); hash = hash * 31 + JodaBeanUtils.hashCode(getProt()); hash = hash * 31 + JodaBeanUtils.hashCode(field); hash = hash * 31 + JodaBeanUtils.hashCode(getManualGet()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("RWOnlyBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("ro").append('=').append(JodaBeanUtils.toString(getRo())).append(',').append(' '); buf.append("wo").append('=').append(JodaBeanUtils.toString(wo)).append(',').append(' '); buf.append("fin").append('=').append(JodaBeanUtils.toString(getFin())).append(',').append(' '); buf.append("priv").append('=').append(JodaBeanUtils.toString(getPriv())).append(',').append(' '); buf.append("pkg").append('=').append(JodaBeanUtils.toString(getPkg())).append(',').append(' '); buf.append("prot").append('=').append(JodaBeanUtils.toString(getProt())).append(',').append(' '); buf.append("field").append('=').append(JodaBeanUtils.toString(field)).append(',').append(' '); buf.append("manualGet").append('=').append(JodaBeanUtils.toString(getManualGet())).append(',').append(' '); buf.append("derived").append('=').append(JodaBeanUtils.toString(getDerived())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code RWOnlyBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code ro} property. */ private final MetaProperty ro = DirectMetaProperty.ofReadOnly( this, "ro", RWOnlyBean.class, Object.class); /** * The meta-property for the {@code wo} property. */ private final MetaProperty wo = DirectMetaProperty.ofWriteOnly( this, "wo", RWOnlyBean.class, Object.class); /** * The meta-property for the {@code fin} property. */ private final MetaProperty fin = DirectMetaProperty.ofReadOnly( this, "fin", RWOnlyBean.class, Object.class); /** * The meta-property for the {@code priv} property. */ private final MetaProperty priv = DirectMetaProperty.ofReadWrite( this, "priv", RWOnlyBean.class, String.class); /** * The meta-property for the {@code pkg} property. */ private final MetaProperty pkg = DirectMetaProperty.ofReadWrite( this, "pkg", RWOnlyBean.class, String.class); /** * The meta-property for the {@code prot} property. */ private final MetaProperty prot = DirectMetaProperty.ofReadWrite( this, "prot", RWOnlyBean.class, String.class); /** * The meta-property for the {@code field} property. */ private final MetaProperty field = DirectMetaProperty.ofReadWrite( this, "field", RWOnlyBean.class, String.class); /** * The meta-property for the {@code manualGet} property. */ private final MetaProperty manualGet = DirectMetaProperty.ofReadOnly( this, "manualGet", RWOnlyBean.class, String.class); /** * The meta-property for the {@code derived} property. */ private final MetaProperty derived = DirectMetaProperty.ofDerived( this, "derived", RWOnlyBean.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "ro", "wo", "fin", "priv", "pkg", "prot", "field", "manualGet", "derived"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3645: // ro return this.ro; case 3800: // wo return this.wo; case 101387: // fin return this.fin; case 3449519: // priv return this.priv; case 111052: // pkg return this.pkg; case 3449703: // prot return this.prot; case 97427706: // field return this.field; case 93508016: // manualGet return this.manualGet; case 1556125213: // derived return this.derived; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new RWOnlyBean()); } @Override public Class beanType() { return RWOnlyBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code ro} property. * @return the meta-property, not null */ public final MetaProperty ro() { return ro; } /** * The meta-property for the {@code wo} property. * @return the meta-property, not null */ public final MetaProperty wo() { return wo; } /** * The meta-property for the {@code fin} property. * @return the meta-property, not null */ public final MetaProperty fin() { return fin; } /** * The meta-property for the {@code priv} property. * @return the meta-property, not null */ public final MetaProperty priv() { return priv; } /** * The meta-property for the {@code pkg} property. * @return the meta-property, not null */ public final MetaProperty pkg() { return pkg; } /** * The meta-property for the {@code prot} property. * @return the meta-property, not null */ public final MetaProperty prot() { return prot; } /** * The meta-property for the {@code field} property. * @return the meta-property, not null */ public final MetaProperty field() { return field; } /** * The meta-property for the {@code manualGet} property. * @return the meta-property, not null */ public final MetaProperty manualGet() { return manualGet; } /** * The meta-property for the {@code derived} property. * @return the meta-property, not null */ public final MetaProperty derived() { return derived; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3645: // ro return ((RWOnlyBean) bean).getRo(); case 3800: // wo if (quiet) { return null; } throw new UnsupportedOperationException("Property cannot be read: wo"); case 101387: // fin return ((RWOnlyBean) bean).getFin(); case 3449519: // priv return ((RWOnlyBean) bean).getPriv(); case 111052: // pkg return ((RWOnlyBean) bean).getPkg(); case 3449703: // prot return ((RWOnlyBean) bean).getProt(); case 97427706: // field return ((RWOnlyBean) bean).field; case 93508016: // manualGet return ((RWOnlyBean) bean).getManualGet(); case 1556125213: // derived return ((RWOnlyBean) bean).getDerived(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3645: // ro if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: ro"); case 3800: // wo ((RWOnlyBean) bean).setWo((Object) newValue); return; case 101387: // fin if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: fin"); case 3449519: // priv ((RWOnlyBean) bean).setPriv((String) newValue); return; case 111052: // pkg ((RWOnlyBean) bean).setPkg((String) newValue); return; case 3449703: // prot ((RWOnlyBean) bean).setProt((String) newValue); return; case 97427706: // field ((RWOnlyBean) bean).field = (String) newValue; return; case 93508016: // manualGet if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: manualGet"); case 1556125213: // derived if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: derived"); } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/RecordStrIntPair.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.beans.impl.RecordBean; /** * Mock, used for testing. * * @param first the first * @param second the second */ public record RecordStrIntPair(String first, int second) implements RecordBean { } ================================================ FILE: src/test/java/org/joda/beans/sample/ReflectiveMutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.TypedMetaBean; import org.joda.beans.impl.reflection.ReflectiveMetaBean; /** * Mock reflective bean, used for testing. * * @author Stephen Colebourne */ public final class ReflectiveMutable implements Bean { /** * The number. */ private int number; /** * The number. */ private boolean flag; /** * The street. */ private String street; /** * The city. */ private String city; /** * The meta-bean. */ public static final TypedMetaBean META_BEAN = ReflectiveMetaBean.of(ReflectiveMutable.class, "number", "flag", "street", "city"); @Override public TypedMetaBean metaBean() { return META_BEAN; } //----------------------------------------------------------------------- /** * Gets the number. * @return the value of the property */ public int getNumber() { return number; } /** * Sets the number. * @param number the new value of the property */ public void setNumber(int number) { this.number = number; } /** * Gets the number. * @return the value of the property */ public boolean isFlag() { return flag; } /** * Sets the number. * @param flag the new value of the property */ public void setFlag(boolean flag) { this.flag = flag; } /** * Gets the street. * @return the value of the property */ public String getStreet() { return street; } /** * Sets the street. * @param street the new value of the property, not null */ public void setStreet(String street) { JodaBeanUtils.notNull(street, "street"); this.street = street; } /** * Gets the city. * @return the value of the property */ public String getCity() { return city; } /** * Sets the city. * @param city the new value of the property, not null */ public void setCity(String city) { JodaBeanUtils.notNull(city, "city"); this.city = city; } } ================================================ FILE: src/test/java/org/joda/beans/sample/Risk.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.convert.FromStringFactory; import org.joda.convert.ToString; /** * Mock extensible enum interface. * * @author Stephen Colebourne */ @FromStringFactory(factory = RiskFactory.class) public interface Risk { int level(); @Override @ToString String toString(); } ================================================ FILE: src/test/java/org/joda/beans/sample/RiskFactory.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.convert.FromString; /** * Mock Joda-Convert factory. * * @author Stephen Colebourne */ public class RiskFactory { @FromString public static Risk risk(String str) { return RiskLevel.valueOf(str); } } ================================================ FILE: src/test/java/org/joda/beans/sample/RiskLevel.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; /** * Mock enum with subclasses. * * @author Stephen Colebourne */ public enum RiskLevel implements Risk { LOW { @Override public int level() { return 0; } }, MEDIUM { @Override public int level() { return 0; } }, HIGH { @Override public int level() { return 0; } }; @Override public abstract int level(); } ================================================ FILE: src/test/java/org/joda/beans/sample/RiskPerception.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; /** * Mock enum. * * @author Stephen Colebourne */ public enum RiskPerception { LOW, MEDIUM , HIGH; } ================================================ FILE: src/test/java/org/joda/beans/sample/SimpleAnnotation.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Used to test annotation parsing. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface SimpleAnnotation { String first() default ""; String second() default ""; String third() default ""; } ================================================ FILE: src/test/java/org/joda/beans/sample/SimpleJson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.io.Serializable; import java.util.Arrays; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(constructorScope = "private") public final class SimpleJson implements ImmutableBean, Serializable { @PropertyDefinition private final char primitiveChar; @PropertyDefinition private final byte primitiveByte; @PropertyDefinition private final short primitiveShort; @PropertyDefinition private final int primitiveInt; @PropertyDefinition private final long primitiveLong; @PropertyDefinition private final float primitiveFloat; @PropertyDefinition private final double primitiveDouble; @PropertyDefinition private final double primitiveDoubleNaN; @PropertyDefinition private final double primitiveDoubleInf; @PropertyDefinition private final Number abstractNumber; @PropertyDefinition private final byte[] arrayByte; @PropertyDefinition private final String[][] array2d; @PropertyDefinition private final String string; @PropertyDefinition private final ImmKey bean; @PropertyDefinition private final Object object1; @PropertyDefinition private final Object object2; @PropertyDefinition private final Risk risk; @PropertyDefinition private final RiskLevel riskLevel; @PropertyDefinition private final EnumSet riskLevels; @PropertyDefinition private final ImmutableList stringList; @PropertyDefinition private final ImmutableList beanList; @PropertyDefinition private final ImmutableMap stringMap; @PropertyDefinition private final ImmutableMap intKeyMap; @PropertyDefinition private final ImmutableMap beanMap; @PropertyDefinition private final ImmutableMap> listInMap; @PropertyDefinition private final ImmutableMap> listNumericInMap; @PropertyDefinition private final ImmutableMap objectInMap; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimpleJson}. * @return the meta-bean, not null */ public static SimpleJson.Meta meta() { return SimpleJson.Meta.INSTANCE; } static { MetaBean.register(SimpleJson.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static SimpleJson.Builder builder() { return new SimpleJson.Builder(); } private SimpleJson( char primitiveChar, byte primitiveByte, short primitiveShort, int primitiveInt, long primitiveLong, float primitiveFloat, double primitiveDouble, double primitiveDoubleNaN, double primitiveDoubleInf, Number abstractNumber, byte[] arrayByte, String[][] array2d, String string, ImmKey bean, Object object1, Object object2, Risk risk, RiskLevel riskLevel, Set riskLevels, List stringList, List beanList, Map stringMap, Map intKeyMap, Map beanMap, Map> listInMap, Map> listNumericInMap, Map objectInMap) { this.primitiveChar = primitiveChar; this.primitiveByte = primitiveByte; this.primitiveShort = primitiveShort; this.primitiveInt = primitiveInt; this.primitiveLong = primitiveLong; this.primitiveFloat = primitiveFloat; this.primitiveDouble = primitiveDouble; this.primitiveDoubleNaN = primitiveDoubleNaN; this.primitiveDoubleInf = primitiveDoubleInf; this.abstractNumber = abstractNumber; this.arrayByte = (arrayByte != null ? arrayByte.clone() : null); this.array2d = (String[][]) JodaBeanUtils.cloneArray(array2d); this.string = string; this.bean = bean; this.object1 = object1; this.object2 = object2; this.risk = risk; this.riskLevel = riskLevel; this.riskLevels = (riskLevels != null ? EnumSet.copyOf(riskLevels) : null); this.stringList = (stringList != null ? ImmutableList.copyOf(stringList) : null); this.beanList = (beanList != null ? ImmutableList.copyOf(beanList) : null); this.stringMap = (stringMap != null ? ImmutableMap.copyOf(stringMap) : null); this.intKeyMap = (intKeyMap != null ? ImmutableMap.copyOf(intKeyMap) : null); this.beanMap = (beanMap != null ? ImmutableMap.copyOf(beanMap) : null); this.listInMap = (listInMap != null ? ImmutableMap.copyOf(listInMap) : null); this.listNumericInMap = (listNumericInMap != null ? ImmutableMap.copyOf(listNumericInMap) : null); this.objectInMap = (objectInMap != null ? ImmutableMap.copyOf(objectInMap) : null); } @Override public SimpleJson.Meta metaBean() { return SimpleJson.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the primitiveChar. * @return the value of the property */ public char getPrimitiveChar() { return primitiveChar; } //----------------------------------------------------------------------- /** * Gets the primitiveByte. * @return the value of the property */ public byte getPrimitiveByte() { return primitiveByte; } //----------------------------------------------------------------------- /** * Gets the primitiveShort. * @return the value of the property */ public short getPrimitiveShort() { return primitiveShort; } //----------------------------------------------------------------------- /** * Gets the primitiveInt. * @return the value of the property */ public int getPrimitiveInt() { return primitiveInt; } //----------------------------------------------------------------------- /** * Gets the primitiveLong. * @return the value of the property */ public long getPrimitiveLong() { return primitiveLong; } //----------------------------------------------------------------------- /** * Gets the primitiveFloat. * @return the value of the property */ public float getPrimitiveFloat() { return primitiveFloat; } //----------------------------------------------------------------------- /** * Gets the primitiveDouble. * @return the value of the property */ public double getPrimitiveDouble() { return primitiveDouble; } //----------------------------------------------------------------------- /** * Gets the primitiveDoubleNaN. * @return the value of the property */ public double getPrimitiveDoubleNaN() { return primitiveDoubleNaN; } //----------------------------------------------------------------------- /** * Gets the primitiveDoubleInf. * @return the value of the property */ public double getPrimitiveDoubleInf() { return primitiveDoubleInf; } //----------------------------------------------------------------------- /** * Gets the abstractNumber. * @return the value of the property */ public Number getAbstractNumber() { return abstractNumber; } //----------------------------------------------------------------------- /** * Gets the arrayByte. * @return the value of the property */ public byte[] getArrayByte() { return (arrayByte != null ? arrayByte.clone() : null); } //----------------------------------------------------------------------- /** * Gets the array2d. * @return the value of the property */ public String[][] getArray2d() { return (String[][]) JodaBeanUtils.cloneArray(array2d); } //----------------------------------------------------------------------- /** * Gets the string. * @return the value of the property */ public String getString() { return string; } //----------------------------------------------------------------------- /** * Gets the bean. * @return the value of the property */ public ImmKey getBean() { return bean; } //----------------------------------------------------------------------- /** * Gets the object1. * @return the value of the property */ public Object getObject1() { return object1; } //----------------------------------------------------------------------- /** * Gets the object2. * @return the value of the property */ public Object getObject2() { return object2; } //----------------------------------------------------------------------- /** * Gets the risk. * @return the value of the property */ public Risk getRisk() { return risk; } //----------------------------------------------------------------------- /** * Gets the riskLevel. * @return the value of the property */ public RiskLevel getRiskLevel() { return riskLevel; } //----------------------------------------------------------------------- /** * Gets the riskLevels. * @return the value of the property */ public EnumSet getRiskLevels() { return riskLevels; } //----------------------------------------------------------------------- /** * Gets the stringList. * @return the value of the property */ public ImmutableList getStringList() { return stringList; } //----------------------------------------------------------------------- /** * Gets the beanList. * @return the value of the property */ public ImmutableList getBeanList() { return beanList; } //----------------------------------------------------------------------- /** * Gets the stringMap. * @return the value of the property */ public ImmutableMap getStringMap() { return stringMap; } //----------------------------------------------------------------------- /** * Gets the intKeyMap. * @return the value of the property */ public ImmutableMap getIntKeyMap() { return intKeyMap; } //----------------------------------------------------------------------- /** * Gets the beanMap. * @return the value of the property */ public ImmutableMap getBeanMap() { return beanMap; } //----------------------------------------------------------------------- /** * Gets the listInMap. * @return the value of the property */ public ImmutableMap> getListInMap() { return listInMap; } //----------------------------------------------------------------------- /** * Gets the listNumericInMap. * @return the value of the property */ public ImmutableMap> getListNumericInMap() { return listNumericInMap; } //----------------------------------------------------------------------- /** * Gets the objectInMap. * @return the value of the property */ public ImmutableMap getObjectInMap() { return objectInMap; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimpleJson other = (SimpleJson) obj; return (this.primitiveChar == other.primitiveChar) && (this.primitiveByte == other.primitiveByte) && (this.primitiveShort == other.primitiveShort) && (this.primitiveInt == other.primitiveInt) && (this.primitiveLong == other.primitiveLong) && JodaBeanUtils.equal(this.primitiveFloat, other.primitiveFloat) && JodaBeanUtils.equal(this.primitiveDouble, other.primitiveDouble) && JodaBeanUtils.equal(this.primitiveDoubleNaN, other.primitiveDoubleNaN) && JodaBeanUtils.equal(this.primitiveDoubleInf, other.primitiveDoubleInf) && JodaBeanUtils.equal(this.abstractNumber, other.abstractNumber) && JodaBeanUtils.equal(this.arrayByte, other.arrayByte) && JodaBeanUtils.equal(this.array2d, other.array2d) && JodaBeanUtils.equal(this.string, other.string) && JodaBeanUtils.equal(this.bean, other.bean) && JodaBeanUtils.equal(this.object1, other.object1) && JodaBeanUtils.equal(this.object2, other.object2) && JodaBeanUtils.equal(this.risk, other.risk) && JodaBeanUtils.equal(this.riskLevel, other.riskLevel) && JodaBeanUtils.equal(this.riskLevels, other.riskLevels) && JodaBeanUtils.equal(this.stringList, other.stringList) && JodaBeanUtils.equal(this.beanList, other.beanList) && JodaBeanUtils.equal(this.stringMap, other.stringMap) && JodaBeanUtils.equal(this.intKeyMap, other.intKeyMap) && JodaBeanUtils.equal(this.beanMap, other.beanMap) && JodaBeanUtils.equal(this.listInMap, other.listInMap) && JodaBeanUtils.equal(this.listNumericInMap, other.listNumericInMap) && JodaBeanUtils.equal(this.objectInMap, other.objectInMap); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveChar); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveByte); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveShort); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveInt); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveLong); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveFloat); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveDouble); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveDoubleNaN); hash = hash * 31 + JodaBeanUtils.hashCode(primitiveDoubleInf); hash = hash * 31 + JodaBeanUtils.hashCode(abstractNumber); hash = hash * 31 + JodaBeanUtils.hashCode(arrayByte); hash = hash * 31 + JodaBeanUtils.hashCode(array2d); hash = hash * 31 + JodaBeanUtils.hashCode(string); hash = hash * 31 + JodaBeanUtils.hashCode(bean); hash = hash * 31 + JodaBeanUtils.hashCode(object1); hash = hash * 31 + JodaBeanUtils.hashCode(object2); hash = hash * 31 + JodaBeanUtils.hashCode(risk); hash = hash * 31 + JodaBeanUtils.hashCode(riskLevel); hash = hash * 31 + JodaBeanUtils.hashCode(riskLevels); hash = hash * 31 + JodaBeanUtils.hashCode(stringList); hash = hash * 31 + JodaBeanUtils.hashCode(beanList); hash = hash * 31 + JodaBeanUtils.hashCode(stringMap); hash = hash * 31 + JodaBeanUtils.hashCode(intKeyMap); hash = hash * 31 + JodaBeanUtils.hashCode(beanMap); hash = hash * 31 + JodaBeanUtils.hashCode(listInMap); hash = hash * 31 + JodaBeanUtils.hashCode(listNumericInMap); hash = hash * 31 + JodaBeanUtils.hashCode(objectInMap); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(896); buf.append("SimpleJson{"); buf.append("primitiveChar").append('=').append(JodaBeanUtils.toString(primitiveChar)).append(',').append(' '); buf.append("primitiveByte").append('=').append(JodaBeanUtils.toString(primitiveByte)).append(',').append(' '); buf.append("primitiveShort").append('=').append(JodaBeanUtils.toString(primitiveShort)).append(',').append(' '); buf.append("primitiveInt").append('=').append(JodaBeanUtils.toString(primitiveInt)).append(',').append(' '); buf.append("primitiveLong").append('=').append(JodaBeanUtils.toString(primitiveLong)).append(',').append(' '); buf.append("primitiveFloat").append('=').append(JodaBeanUtils.toString(primitiveFloat)).append(',').append(' '); buf.append("primitiveDouble").append('=').append(JodaBeanUtils.toString(primitiveDouble)).append(',').append(' '); buf.append("primitiveDoubleNaN").append('=').append(JodaBeanUtils.toString(primitiveDoubleNaN)).append(',').append(' '); buf.append("primitiveDoubleInf").append('=').append(JodaBeanUtils.toString(primitiveDoubleInf)).append(',').append(' '); buf.append("abstractNumber").append('=').append(JodaBeanUtils.toString(abstractNumber)).append(',').append(' '); buf.append("arrayByte").append('=').append(JodaBeanUtils.toString(arrayByte)).append(',').append(' '); buf.append("array2d").append('=').append(JodaBeanUtils.toString(array2d)).append(',').append(' '); buf.append("string").append('=').append(JodaBeanUtils.toString(string)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("object1").append('=').append(JodaBeanUtils.toString(object1)).append(',').append(' '); buf.append("object2").append('=').append(JodaBeanUtils.toString(object2)).append(',').append(' '); buf.append("risk").append('=').append(JodaBeanUtils.toString(risk)).append(',').append(' '); buf.append("riskLevel").append('=').append(JodaBeanUtils.toString(riskLevel)).append(',').append(' '); buf.append("riskLevels").append('=').append(JodaBeanUtils.toString(riskLevels)).append(',').append(' '); buf.append("stringList").append('=').append(JodaBeanUtils.toString(stringList)).append(',').append(' '); buf.append("beanList").append('=').append(JodaBeanUtils.toString(beanList)).append(',').append(' '); buf.append("stringMap").append('=').append(JodaBeanUtils.toString(stringMap)).append(',').append(' '); buf.append("intKeyMap").append('=').append(JodaBeanUtils.toString(intKeyMap)).append(',').append(' '); buf.append("beanMap").append('=').append(JodaBeanUtils.toString(beanMap)).append(',').append(' '); buf.append("listInMap").append('=').append(JodaBeanUtils.toString(listInMap)).append(',').append(' '); buf.append("listNumericInMap").append('=').append(JodaBeanUtils.toString(listNumericInMap)).append(',').append(' '); buf.append("objectInMap").append('=').append(JodaBeanUtils.toString(objectInMap)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimpleJson}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code primitiveChar} property. */ private final MetaProperty primitiveChar = DirectMetaProperty.ofImmutable( this, "primitiveChar", SimpleJson.class, Character.TYPE); /** * The meta-property for the {@code primitiveByte} property. */ private final MetaProperty primitiveByte = DirectMetaProperty.ofImmutable( this, "primitiveByte", SimpleJson.class, Byte.TYPE); /** * The meta-property for the {@code primitiveShort} property. */ private final MetaProperty primitiveShort = DirectMetaProperty.ofImmutable( this, "primitiveShort", SimpleJson.class, Short.TYPE); /** * The meta-property for the {@code primitiveInt} property. */ private final MetaProperty primitiveInt = DirectMetaProperty.ofImmutable( this, "primitiveInt", SimpleJson.class, Integer.TYPE); /** * The meta-property for the {@code primitiveLong} property. */ private final MetaProperty primitiveLong = DirectMetaProperty.ofImmutable( this, "primitiveLong", SimpleJson.class, Long.TYPE); /** * The meta-property for the {@code primitiveFloat} property. */ private final MetaProperty primitiveFloat = DirectMetaProperty.ofImmutable( this, "primitiveFloat", SimpleJson.class, Float.TYPE); /** * The meta-property for the {@code primitiveDouble} property. */ private final MetaProperty primitiveDouble = DirectMetaProperty.ofImmutable( this, "primitiveDouble", SimpleJson.class, Double.TYPE); /** * The meta-property for the {@code primitiveDoubleNaN} property. */ private final MetaProperty primitiveDoubleNaN = DirectMetaProperty.ofImmutable( this, "primitiveDoubleNaN", SimpleJson.class, Double.TYPE); /** * The meta-property for the {@code primitiveDoubleInf} property. */ private final MetaProperty primitiveDoubleInf = DirectMetaProperty.ofImmutable( this, "primitiveDoubleInf", SimpleJson.class, Double.TYPE); /** * The meta-property for the {@code abstractNumber} property. */ private final MetaProperty abstractNumber = DirectMetaProperty.ofImmutable( this, "abstractNumber", SimpleJson.class, Number.class); /** * The meta-property for the {@code arrayByte} property. */ private final MetaProperty arrayByte = DirectMetaProperty.ofImmutable( this, "arrayByte", SimpleJson.class, byte[].class); /** * The meta-property for the {@code array2d} property. */ private final MetaProperty array2d = DirectMetaProperty.ofImmutable( this, "array2d", SimpleJson.class, String[][].class); /** * The meta-property for the {@code string} property. */ private final MetaProperty string = DirectMetaProperty.ofImmutable( this, "string", SimpleJson.class, String.class); /** * The meta-property for the {@code bean} property. */ private final MetaProperty bean = DirectMetaProperty.ofImmutable( this, "bean", SimpleJson.class, ImmKey.class); /** * The meta-property for the {@code object1} property. */ private final MetaProperty object1 = DirectMetaProperty.ofImmutable( this, "object1", SimpleJson.class, Object.class); /** * The meta-property for the {@code object2} property. */ private final MetaProperty object2 = DirectMetaProperty.ofImmutable( this, "object2", SimpleJson.class, Object.class); /** * The meta-property for the {@code risk} property. */ private final MetaProperty risk = DirectMetaProperty.ofImmutable( this, "risk", SimpleJson.class, Risk.class); /** * The meta-property for the {@code riskLevel} property. */ private final MetaProperty riskLevel = DirectMetaProperty.ofImmutable( this, "riskLevel", SimpleJson.class, RiskLevel.class); /** * The meta-property for the {@code riskLevels} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> riskLevels = DirectMetaProperty.ofImmutable( this, "riskLevels", SimpleJson.class, (Class) EnumSet.class); /** * The meta-property for the {@code stringList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> stringList = DirectMetaProperty.ofImmutable( this, "stringList", SimpleJson.class, (Class) ImmutableList.class); /** * The meta-property for the {@code beanList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> beanList = DirectMetaProperty.ofImmutable( this, "beanList", SimpleJson.class, (Class) ImmutableList.class); /** * The meta-property for the {@code stringMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> stringMap = DirectMetaProperty.ofImmutable( this, "stringMap", SimpleJson.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code intKeyMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> intKeyMap = DirectMetaProperty.ofImmutable( this, "intKeyMap", SimpleJson.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code beanMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> beanMap = DirectMetaProperty.ofImmutable( this, "beanMap", SimpleJson.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code listInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> listInMap = DirectMetaProperty.ofImmutable( this, "listInMap", SimpleJson.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code listNumericInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> listNumericInMap = DirectMetaProperty.ofImmutable( this, "listNumericInMap", SimpleJson.class, (Class) ImmutableMap.class); /** * The meta-property for the {@code objectInMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> objectInMap = DirectMetaProperty.ofImmutable( this, "objectInMap", SimpleJson.class, (Class) ImmutableMap.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "primitiveChar", "primitiveByte", "primitiveShort", "primitiveInt", "primitiveLong", "primitiveFloat", "primitiveDouble", "primitiveDoubleNaN", "primitiveDoubleInf", "abstractNumber", "arrayByte", "array2d", "string", "bean", "object1", "object2", "risk", "riskLevel", "riskLevels", "stringList", "beanList", "stringMap", "intKeyMap", "beanMap", "listInMap", "listNumericInMap", "objectInMap"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1058293981: // primitiveChar return this.primitiveChar; case 1058281103: // primitiveByte return this.primitiveByte; case -1537835051: // primitiveShort return this.primitiveShort; case 1281070472: // primitiveInt return this.primitiveInt; case 1058569219: // primitiveLong return this.primitiveLong; case -1549722187: // primitiveFloat return this.primitiveFloat; case -851055720: // primitiveDouble return this.primitiveDouble; case -608928189: // primitiveDoubleNaN return this.primitiveDoubleNaN; case -608932567: // primitiveDoubleInf return this.primitiveDoubleInf; case 1986500107: // abstractNumber return this.abstractNumber; case -1425444095: // arrayByte return this.arrayByte; case -734443893: // array2d return this.array2d; case -891985903: // string return this.string; case 3019696: // bean return this.bean; case -1659648814: // object1 return this.object1; case -1659648813: // object2 return this.object2; case 3500751: // risk return this.risk; case 540453365: // riskLevel return this.riskLevel; case -425814754: // riskLevels return this.riskLevels; case -1573317553: // stringList return this.stringList; case 1321263214: // beanList return this.beanList; case -189298805: // stringMap return this.stringMap; case -253193396: // intKeyMap return this.intKeyMap; case -234472564: // beanMap return this.beanMap; case -1244601351: // listInMap return this.listInMap; case 391098024: // listNumericInMap return this.listNumericInMap; case -1297715720: // objectInMap return this.objectInMap; } return super.metaPropertyGet(propertyName); } @Override public SimpleJson.Builder builder() { return new SimpleJson.Builder(); } @Override public Class beanType() { return SimpleJson.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code primitiveChar} property. * @return the meta-property, not null */ public MetaProperty primitiveChar() { return primitiveChar; } /** * The meta-property for the {@code primitiveByte} property. * @return the meta-property, not null */ public MetaProperty primitiveByte() { return primitiveByte; } /** * The meta-property for the {@code primitiveShort} property. * @return the meta-property, not null */ public MetaProperty primitiveShort() { return primitiveShort; } /** * The meta-property for the {@code primitiveInt} property. * @return the meta-property, not null */ public MetaProperty primitiveInt() { return primitiveInt; } /** * The meta-property for the {@code primitiveLong} property. * @return the meta-property, not null */ public MetaProperty primitiveLong() { return primitiveLong; } /** * The meta-property for the {@code primitiveFloat} property. * @return the meta-property, not null */ public MetaProperty primitiveFloat() { return primitiveFloat; } /** * The meta-property for the {@code primitiveDouble} property. * @return the meta-property, not null */ public MetaProperty primitiveDouble() { return primitiveDouble; } /** * The meta-property for the {@code primitiveDoubleNaN} property. * @return the meta-property, not null */ public MetaProperty primitiveDoubleNaN() { return primitiveDoubleNaN; } /** * The meta-property for the {@code primitiveDoubleInf} property. * @return the meta-property, not null */ public MetaProperty primitiveDoubleInf() { return primitiveDoubleInf; } /** * The meta-property for the {@code abstractNumber} property. * @return the meta-property, not null */ public MetaProperty abstractNumber() { return abstractNumber; } /** * The meta-property for the {@code arrayByte} property. * @return the meta-property, not null */ public MetaProperty arrayByte() { return arrayByte; } /** * The meta-property for the {@code array2d} property. * @return the meta-property, not null */ public MetaProperty array2d() { return array2d; } /** * The meta-property for the {@code string} property. * @return the meta-property, not null */ public MetaProperty string() { return string; } /** * The meta-property for the {@code bean} property. * @return the meta-property, not null */ public MetaProperty bean() { return bean; } /** * The meta-property for the {@code object1} property. * @return the meta-property, not null */ public MetaProperty object1() { return object1; } /** * The meta-property for the {@code object2} property. * @return the meta-property, not null */ public MetaProperty object2() { return object2; } /** * The meta-property for the {@code risk} property. * @return the meta-property, not null */ public MetaProperty risk() { return risk; } /** * The meta-property for the {@code riskLevel} property. * @return the meta-property, not null */ public MetaProperty riskLevel() { return riskLevel; } /** * The meta-property for the {@code riskLevels} property. * @return the meta-property, not null */ public MetaProperty> riskLevels() { return riskLevels; } /** * The meta-property for the {@code stringList} property. * @return the meta-property, not null */ public MetaProperty> stringList() { return stringList; } /** * The meta-property for the {@code beanList} property. * @return the meta-property, not null */ public MetaProperty> beanList() { return beanList; } /** * The meta-property for the {@code stringMap} property. * @return the meta-property, not null */ public MetaProperty> stringMap() { return stringMap; } /** * The meta-property for the {@code intKeyMap} property. * @return the meta-property, not null */ public MetaProperty> intKeyMap() { return intKeyMap; } /** * The meta-property for the {@code beanMap} property. * @return the meta-property, not null */ public MetaProperty> beanMap() { return beanMap; } /** * The meta-property for the {@code listInMap} property. * @return the meta-property, not null */ public MetaProperty>> listInMap() { return listInMap; } /** * The meta-property for the {@code listNumericInMap} property. * @return the meta-property, not null */ public MetaProperty>> listNumericInMap() { return listNumericInMap; } /** * The meta-property for the {@code objectInMap} property. * @return the meta-property, not null */ public MetaProperty> objectInMap() { return objectInMap; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1058293981: // primitiveChar return ((SimpleJson) bean).getPrimitiveChar(); case 1058281103: // primitiveByte return ((SimpleJson) bean).getPrimitiveByte(); case -1537835051: // primitiveShort return ((SimpleJson) bean).getPrimitiveShort(); case 1281070472: // primitiveInt return ((SimpleJson) bean).getPrimitiveInt(); case 1058569219: // primitiveLong return ((SimpleJson) bean).getPrimitiveLong(); case -1549722187: // primitiveFloat return ((SimpleJson) bean).getPrimitiveFloat(); case -851055720: // primitiveDouble return ((SimpleJson) bean).getPrimitiveDouble(); case -608928189: // primitiveDoubleNaN return ((SimpleJson) bean).getPrimitiveDoubleNaN(); case -608932567: // primitiveDoubleInf return ((SimpleJson) bean).getPrimitiveDoubleInf(); case 1986500107: // abstractNumber return ((SimpleJson) bean).getAbstractNumber(); case -1425444095: // arrayByte return ((SimpleJson) bean).getArrayByte(); case -734443893: // array2d return ((SimpleJson) bean).getArray2d(); case -891985903: // string return ((SimpleJson) bean).getString(); case 3019696: // bean return ((SimpleJson) bean).getBean(); case -1659648814: // object1 return ((SimpleJson) bean).getObject1(); case -1659648813: // object2 return ((SimpleJson) bean).getObject2(); case 3500751: // risk return ((SimpleJson) bean).getRisk(); case 540453365: // riskLevel return ((SimpleJson) bean).getRiskLevel(); case -425814754: // riskLevels return ((SimpleJson) bean).getRiskLevels(); case -1573317553: // stringList return ((SimpleJson) bean).getStringList(); case 1321263214: // beanList return ((SimpleJson) bean).getBeanList(); case -189298805: // stringMap return ((SimpleJson) bean).getStringMap(); case -253193396: // intKeyMap return ((SimpleJson) bean).getIntKeyMap(); case -234472564: // beanMap return ((SimpleJson) bean).getBeanMap(); case -1244601351: // listInMap return ((SimpleJson) bean).getListInMap(); case 391098024: // listNumericInMap return ((SimpleJson) bean).getListNumericInMap(); case -1297715720: // objectInMap return ((SimpleJson) bean).getObjectInMap(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code SimpleJson}. */ public static final class Builder extends DirectFieldsBeanBuilder { private char primitiveChar; private byte primitiveByte; private short primitiveShort; private int primitiveInt; private long primitiveLong; private float primitiveFloat; private double primitiveDouble; private double primitiveDoubleNaN; private double primitiveDoubleInf; private Number abstractNumber; private byte[] arrayByte; private String[][] array2d; private String string; private ImmKey bean; private Object object1; private Object object2; private Risk risk; private RiskLevel riskLevel; private Set riskLevels; private List stringList; private List beanList; private Map stringMap; private Map intKeyMap; private Map beanMap; private Map> listInMap; private Map> listNumericInMap; private Map objectInMap; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(SimpleJson beanToCopy) { this.primitiveChar = beanToCopy.getPrimitiveChar(); this.primitiveByte = beanToCopy.getPrimitiveByte(); this.primitiveShort = beanToCopy.getPrimitiveShort(); this.primitiveInt = beanToCopy.getPrimitiveInt(); this.primitiveLong = beanToCopy.getPrimitiveLong(); this.primitiveFloat = beanToCopy.getPrimitiveFloat(); this.primitiveDouble = beanToCopy.getPrimitiveDouble(); this.primitiveDoubleNaN = beanToCopy.getPrimitiveDoubleNaN(); this.primitiveDoubleInf = beanToCopy.getPrimitiveDoubleInf(); this.abstractNumber = beanToCopy.getAbstractNumber(); this.arrayByte = (beanToCopy.getArrayByte() != null ? beanToCopy.getArrayByte().clone() : null); this.array2d = (String[][]) JodaBeanUtils.cloneArray(beanToCopy.getArray2d()); this.string = beanToCopy.getString(); this.bean = beanToCopy.getBean(); this.object1 = beanToCopy.getObject1(); this.object2 = beanToCopy.getObject2(); this.risk = beanToCopy.getRisk(); this.riskLevel = beanToCopy.getRiskLevel(); this.riskLevels = (beanToCopy.getRiskLevels() != null ? new HashSet<>(beanToCopy.getRiskLevels()) : null); this.stringList = beanToCopy.getStringList(); this.beanList = beanToCopy.getBeanList(); this.stringMap = beanToCopy.getStringMap(); this.intKeyMap = beanToCopy.getIntKeyMap(); this.beanMap = beanToCopy.getBeanMap(); this.listInMap = beanToCopy.getListInMap(); this.listNumericInMap = beanToCopy.getListNumericInMap(); this.objectInMap = beanToCopy.getObjectInMap(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 1058293981: // primitiveChar return this.primitiveChar; case 1058281103: // primitiveByte return this.primitiveByte; case -1537835051: // primitiveShort return this.primitiveShort; case 1281070472: // primitiveInt return this.primitiveInt; case 1058569219: // primitiveLong return this.primitiveLong; case -1549722187: // primitiveFloat return this.primitiveFloat; case -851055720: // primitiveDouble return this.primitiveDouble; case -608928189: // primitiveDoubleNaN return this.primitiveDoubleNaN; case -608932567: // primitiveDoubleInf return this.primitiveDoubleInf; case 1986500107: // abstractNumber return this.abstractNumber; case -1425444095: // arrayByte return this.arrayByte; case -734443893: // array2d return this.array2d; case -891985903: // string return this.string; case 3019696: // bean return this.bean; case -1659648814: // object1 return this.object1; case -1659648813: // object2 return this.object2; case 3500751: // risk return this.risk; case 540453365: // riskLevel return this.riskLevel; case -425814754: // riskLevels return this.riskLevels; case -1573317553: // stringList return this.stringList; case 1321263214: // beanList return this.beanList; case -189298805: // stringMap return this.stringMap; case -253193396: // intKeyMap return this.intKeyMap; case -234472564: // beanMap return this.beanMap; case -1244601351: // listInMap return this.listInMap; case 391098024: // listNumericInMap return this.listNumericInMap; case -1297715720: // objectInMap return this.objectInMap; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 1058293981: // primitiveChar this.primitiveChar = (Character) newValue; break; case 1058281103: // primitiveByte this.primitiveByte = (Byte) newValue; break; case -1537835051: // primitiveShort this.primitiveShort = (Short) newValue; break; case 1281070472: // primitiveInt this.primitiveInt = (Integer) newValue; break; case 1058569219: // primitiveLong this.primitiveLong = (Long) newValue; break; case -1549722187: // primitiveFloat this.primitiveFloat = (Float) newValue; break; case -851055720: // primitiveDouble this.primitiveDouble = (Double) newValue; break; case -608928189: // primitiveDoubleNaN this.primitiveDoubleNaN = (Double) newValue; break; case -608932567: // primitiveDoubleInf this.primitiveDoubleInf = (Double) newValue; break; case 1986500107: // abstractNumber this.abstractNumber = (Number) newValue; break; case -1425444095: // arrayByte this.arrayByte = (byte[]) newValue; break; case -734443893: // array2d this.array2d = (String[][]) newValue; break; case -891985903: // string this.string = (String) newValue; break; case 3019696: // bean this.bean = (ImmKey) newValue; break; case -1659648814: // object1 this.object1 = (Object) newValue; break; case -1659648813: // object2 this.object2 = (Object) newValue; break; case 3500751: // risk this.risk = (Risk) newValue; break; case 540453365: // riskLevel this.riskLevel = (RiskLevel) newValue; break; case -425814754: // riskLevels this.riskLevels = (Set) newValue; break; case -1573317553: // stringList this.stringList = (List) newValue; break; case 1321263214: // beanList this.beanList = (List) newValue; break; case -189298805: // stringMap this.stringMap = (Map) newValue; break; case -253193396: // intKeyMap this.intKeyMap = (Map) newValue; break; case -234472564: // beanMap this.beanMap = (Map) newValue; break; case -1244601351: // listInMap this.listInMap = (Map>) newValue; break; case 391098024: // listNumericInMap this.listNumericInMap = (Map>) newValue; break; case -1297715720: // objectInMap this.objectInMap = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public SimpleJson build() { return new SimpleJson( primitiveChar, primitiveByte, primitiveShort, primitiveInt, primitiveLong, primitiveFloat, primitiveDouble, primitiveDoubleNaN, primitiveDoubleInf, abstractNumber, arrayByte, array2d, string, bean, object1, object2, risk, riskLevel, riskLevels, stringList, beanList, stringMap, intKeyMap, beanMap, listInMap, listNumericInMap, objectInMap); } //----------------------------------------------------------------------- /** * Sets the primitiveChar. * @param primitiveChar the new value * @return this, for chaining, not null */ public Builder primitiveChar(char primitiveChar) { this.primitiveChar = primitiveChar; return this; } /** * Sets the primitiveByte. * @param primitiveByte the new value * @return this, for chaining, not null */ public Builder primitiveByte(byte primitiveByte) { this.primitiveByte = primitiveByte; return this; } /** * Sets the primitiveShort. * @param primitiveShort the new value * @return this, for chaining, not null */ public Builder primitiveShort(short primitiveShort) { this.primitiveShort = primitiveShort; return this; } /** * Sets the primitiveInt. * @param primitiveInt the new value * @return this, for chaining, not null */ public Builder primitiveInt(int primitiveInt) { this.primitiveInt = primitiveInt; return this; } /** * Sets the primitiveLong. * @param primitiveLong the new value * @return this, for chaining, not null */ public Builder primitiveLong(long primitiveLong) { this.primitiveLong = primitiveLong; return this; } /** * Sets the primitiveFloat. * @param primitiveFloat the new value * @return this, for chaining, not null */ public Builder primitiveFloat(float primitiveFloat) { this.primitiveFloat = primitiveFloat; return this; } /** * Sets the primitiveDouble. * @param primitiveDouble the new value * @return this, for chaining, not null */ public Builder primitiveDouble(double primitiveDouble) { this.primitiveDouble = primitiveDouble; return this; } /** * Sets the primitiveDoubleNaN. * @param primitiveDoubleNaN the new value * @return this, for chaining, not null */ public Builder primitiveDoubleNaN(double primitiveDoubleNaN) { this.primitiveDoubleNaN = primitiveDoubleNaN; return this; } /** * Sets the primitiveDoubleInf. * @param primitiveDoubleInf the new value * @return this, for chaining, not null */ public Builder primitiveDoubleInf(double primitiveDoubleInf) { this.primitiveDoubleInf = primitiveDoubleInf; return this; } /** * Sets the abstractNumber. * @param abstractNumber the new value * @return this, for chaining, not null */ public Builder abstractNumber(Number abstractNumber) { this.abstractNumber = abstractNumber; return this; } /** * Sets the arrayByte. * @param arrayByte the new value * @return this, for chaining, not null */ public Builder arrayByte(byte[] arrayByte) { this.arrayByte = arrayByte; return this; } /** * Sets the array2d. * @param array2d the new value * @return this, for chaining, not null */ public Builder array2d(String[][] array2d) { this.array2d = array2d; return this; } /** * Sets the string. * @param string the new value * @return this, for chaining, not null */ public Builder string(String string) { this.string = string; return this; } /** * Sets the bean. * @param bean the new value * @return this, for chaining, not null */ public Builder bean(ImmKey bean) { this.bean = bean; return this; } /** * Sets the object1. * @param object1 the new value * @return this, for chaining, not null */ public Builder object1(Object object1) { this.object1 = object1; return this; } /** * Sets the object2. * @param object2 the new value * @return this, for chaining, not null */ public Builder object2(Object object2) { this.object2 = object2; return this; } /** * Sets the risk. * @param risk the new value * @return this, for chaining, not null */ public Builder risk(Risk risk) { this.risk = risk; return this; } /** * Sets the riskLevel. * @param riskLevel the new value * @return this, for chaining, not null */ public Builder riskLevel(RiskLevel riskLevel) { this.riskLevel = riskLevel; return this; } /** * Sets the riskLevels. * @param riskLevels the new value * @return this, for chaining, not null */ public Builder riskLevels(Set riskLevels) { this.riskLevels = riskLevels; return this; } /** * Sets the {@code riskLevels} property in the builder * from an array of objects. * @param riskLevels the new value * @return this, for chaining, not null */ public Builder riskLevels(RiskLevel... riskLevels) { return riskLevels(EnumSet.copyOf(Arrays.asList(riskLevels))); } /** * Sets the stringList. * @param stringList the new value * @return this, for chaining, not null */ public Builder stringList(List stringList) { this.stringList = stringList; return this; } /** * Sets the {@code stringList} property in the builder * from an array of objects. * @param stringList the new value * @return this, for chaining, not null */ public Builder stringList(String... stringList) { return stringList(ImmutableList.copyOf(stringList)); } /** * Sets the beanList. * @param beanList the new value * @return this, for chaining, not null */ public Builder beanList(List beanList) { this.beanList = beanList; return this; } /** * Sets the {@code beanList} property in the builder * from an array of objects. * @param beanList the new value * @return this, for chaining, not null */ public Builder beanList(ImmKey... beanList) { return beanList(ImmutableList.copyOf(beanList)); } /** * Sets the stringMap. * @param stringMap the new value * @return this, for chaining, not null */ public Builder stringMap(Map stringMap) { this.stringMap = stringMap; return this; } /** * Sets the intKeyMap. * @param intKeyMap the new value * @return this, for chaining, not null */ public Builder intKeyMap(Map intKeyMap) { this.intKeyMap = intKeyMap; return this; } /** * Sets the beanMap. * @param beanMap the new value * @return this, for chaining, not null */ public Builder beanMap(Map beanMap) { this.beanMap = beanMap; return this; } /** * Sets the listInMap. * @param listInMap the new value * @return this, for chaining, not null */ public Builder listInMap(Map> listInMap) { this.listInMap = listInMap; return this; } /** * Sets the listNumericInMap. * @param listNumericInMap the new value * @return this, for chaining, not null */ public Builder listNumericInMap(Map> listNumericInMap) { this.listNumericInMap = listNumericInMap; return this; } /** * Sets the objectInMap. * @param objectInMap the new value * @return this, for chaining, not null */ public Builder objectInMap(Map objectInMap) { this.objectInMap = objectInMap; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(896); buf.append("SimpleJson.Builder{"); buf.append("primitiveChar").append('=').append(JodaBeanUtils.toString(primitiveChar)).append(',').append(' '); buf.append("primitiveByte").append('=').append(JodaBeanUtils.toString(primitiveByte)).append(',').append(' '); buf.append("primitiveShort").append('=').append(JodaBeanUtils.toString(primitiveShort)).append(',').append(' '); buf.append("primitiveInt").append('=').append(JodaBeanUtils.toString(primitiveInt)).append(',').append(' '); buf.append("primitiveLong").append('=').append(JodaBeanUtils.toString(primitiveLong)).append(',').append(' '); buf.append("primitiveFloat").append('=').append(JodaBeanUtils.toString(primitiveFloat)).append(',').append(' '); buf.append("primitiveDouble").append('=').append(JodaBeanUtils.toString(primitiveDouble)).append(',').append(' '); buf.append("primitiveDoubleNaN").append('=').append(JodaBeanUtils.toString(primitiveDoubleNaN)).append(',').append(' '); buf.append("primitiveDoubleInf").append('=').append(JodaBeanUtils.toString(primitiveDoubleInf)).append(',').append(' '); buf.append("abstractNumber").append('=').append(JodaBeanUtils.toString(abstractNumber)).append(',').append(' '); buf.append("arrayByte").append('=').append(JodaBeanUtils.toString(arrayByte)).append(',').append(' '); buf.append("array2d").append('=').append(JodaBeanUtils.toString(array2d)).append(',').append(' '); buf.append("string").append('=').append(JodaBeanUtils.toString(string)).append(',').append(' '); buf.append("bean").append('=').append(JodaBeanUtils.toString(bean)).append(',').append(' '); buf.append("object1").append('=').append(JodaBeanUtils.toString(object1)).append(',').append(' '); buf.append("object2").append('=').append(JodaBeanUtils.toString(object2)).append(',').append(' '); buf.append("risk").append('=').append(JodaBeanUtils.toString(risk)).append(',').append(' '); buf.append("riskLevel").append('=').append(JodaBeanUtils.toString(riskLevel)).append(',').append(' '); buf.append("riskLevels").append('=').append(JodaBeanUtils.toString(riskLevels)).append(',').append(' '); buf.append("stringList").append('=').append(JodaBeanUtils.toString(stringList)).append(',').append(' '); buf.append("beanList").append('=').append(JodaBeanUtils.toString(beanList)).append(',').append(' '); buf.append("stringMap").append('=').append(JodaBeanUtils.toString(stringMap)).append(',').append(' '); buf.append("intKeyMap").append('=').append(JodaBeanUtils.toString(intKeyMap)).append(',').append(' '); buf.append("beanMap").append('=').append(JodaBeanUtils.toString(beanMap)).append(',').append(' '); buf.append("listInMap").append('=').append(JodaBeanUtils.toString(listInMap)).append(',').append(' '); buf.append("listNumericInMap").append('=').append(JodaBeanUtils.toString(listNumericInMap)).append(',').append(' '); buf.append("objectInMap").append('=').append(JodaBeanUtils.toString(objectInMap)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SimpleName.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock address JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class SimpleName implements Bean { /** The forename. */ @PropertyDefinition(alias = "firstName") private String forename; /** The middle names. */ @PropertyDefinition private String[] middleNames; /** The surname. */ @PropertyDefinition(alias = "givenName") private String surname; /** * Creates an instance. */ public SimpleName() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimpleName}. * @return the meta-bean, not null */ public static SimpleName.Meta meta() { return SimpleName.Meta.INSTANCE; } static { MetaBean.register(SimpleName.Meta.INSTANCE); } @Override public SimpleName.Meta metaBean() { return SimpleName.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } /** * Sets the forename. * @param forename the new value of the property */ public void setForename(String forename) { this.forename = forename; } /** * Gets the the {@code forename} property. * @return the property, not null */ public final Property forename() { return metaBean().forename().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the middle names. * @return the value of the property */ public String[] getMiddleNames() { return middleNames; } /** * Sets the middle names. * @param middleNames the new value of the property */ public void setMiddleNames(String[] middleNames) { this.middleNames = middleNames; } /** * Gets the the {@code middleNames} property. * @return the property, not null */ public final Property middleNames() { return metaBean().middleNames().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public String getSurname() { return surname; } /** * Sets the surname. * @param surname the new value of the property */ public void setSurname(String surname) { this.surname = surname; } /** * Gets the the {@code surname} property. * @return the property, not null */ public final Property surname() { return metaBean().surname().createProperty(this); } //----------------------------------------------------------------------- @Override public SimpleName clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimpleName other = (SimpleName) obj; return JodaBeanUtils.equal(this.getForename(), other.getForename()) && JodaBeanUtils.equal(this.getMiddleNames(), other.getMiddleNames()) && JodaBeanUtils.equal(this.getSurname(), other.getSurname()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getForename()); hash = hash * 31 + JodaBeanUtils.hashCode(getMiddleNames()); hash = hash * 31 + JodaBeanUtils.hashCode(getSurname()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("SimpleName{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(getForename())).append(',').append(' '); buf.append("middleNames").append('=').append(JodaBeanUtils.toString(getMiddleNames())).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(getSurname())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimpleName}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofReadWrite( this, "forename", SimpleName.class, String.class); /** * The meta-property for the {@code middleNames} property. */ private final MetaProperty middleNames = DirectMetaProperty.ofReadWrite( this, "middleNames", SimpleName.class, String[].class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofReadWrite( this, "surname", SimpleName.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "middleNames", "surname"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename case 132835675: // firstName (alias) return this.forename; case 404996787: // middleNames return this.middleNames; case -1852993317: // surname case 1469046696: // givenName (alias) return this.surname; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new SimpleName()); } @Override public Class beanType() { return SimpleName.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public final MetaProperty forename() { return forename; } /** * The meta-property for the {@code middleNames} property. * @return the meta-property, not null */ public final MetaProperty middleNames() { return middleNames; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public final MetaProperty surname() { return surname; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename case 132835675: // firstName (alias) return ((SimpleName) bean).getForename(); case 404996787: // middleNames return ((SimpleName) bean).getMiddleNames(); case -1852993317: // surname case 1469046696: // givenName (alias) return ((SimpleName) bean).getSurname(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename case 132835675: // firstName (alias) ((SimpleName) bean).setForename((String) newValue); return; case 404996787: // middleNames ((SimpleName) bean).setMiddleNames((String[]) newValue); return; case -1852993317: // surname case 1469046696: // givenName (alias) ((SimpleName) bean).setSurname((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SimplePerson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import org.joda.beans.impl.flexi.FlexiBean; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class SimplePerson implements Cloneable, Bean { /** The forename. */ @PropertyDefinition private String forename; /** The surname. */ @PropertyDefinition private String surname; /** The number of cars. */ @PropertyDefinition private transient int numberOfCars; @PropertyDefinition private final List
addressList = new ArrayList<>(); @PropertyDefinition private final Map otherAddressMap = new HashMap<>(); @PropertyDefinition private final List> addressesList = new ArrayList<>(); @PropertyDefinition private Address mainAddress; @Deprecated @PropertyDefinition private final FlexiBean propDefAnnotationSecondDeprecated = new FlexiBean(); @SimpleAnnotation(first = "additionalAttributes") @PropertyDefinition(get = "manual") private Map propDefAnnotationSecondManual; public Map getPropDefAnnotationSecondManual() { return this.propDefAnnotationSecondManual; } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimplePerson}. * @return the meta-bean, not null */ public static SimplePerson.Meta meta() { return SimplePerson.Meta.INSTANCE; } static { MetaBean.register(SimplePerson.Meta.INSTANCE); } @Override public SimplePerson.Meta metaBean() { return SimplePerson.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } /** * Sets the forename. * @param forename the new value of the property */ public void setForename(String forename) { this.forename = forename; } /** * Gets the the {@code forename} property. * @return the property, not null */ public Property forename() { return metaBean().forename().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public String getSurname() { return surname; } /** * Sets the surname. * @param surname the new value of the property */ public void setSurname(String surname) { this.surname = surname; } /** * Gets the the {@code surname} property. * @return the property, not null */ public Property surname() { return metaBean().surname().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the number of cars. * @return the value of the property */ public int getNumberOfCars() { return numberOfCars; } /** * Sets the number of cars. * @param numberOfCars the new value of the property */ public void setNumberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; } /** * Gets the the {@code numberOfCars} property. * @return the property, not null */ public Property numberOfCars() { return metaBean().numberOfCars().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressList. * @return the value of the property, not null */ public List
getAddressList() { return addressList; } /** * Sets the addressList. * @param addressList the new value of the property, not null */ public void setAddressList(List
addressList) { JodaBeanUtils.notNull(addressList, "addressList"); this.addressList.clear(); this.addressList.addAll(addressList); } /** * Gets the the {@code addressList} property. * @return the property, not null */ public Property> addressList() { return metaBean().addressList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the otherAddressMap. * @return the value of the property, not null */ public Map getOtherAddressMap() { return otherAddressMap; } /** * Sets the otherAddressMap. * @param otherAddressMap the new value of the property, not null */ public void setOtherAddressMap(Map otherAddressMap) { JodaBeanUtils.notNull(otherAddressMap, "otherAddressMap"); this.otherAddressMap.clear(); this.otherAddressMap.putAll(otherAddressMap); } /** * Gets the the {@code otherAddressMap} property. * @return the property, not null */ public Property> otherAddressMap() { return metaBean().otherAddressMap().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressesList. * @return the value of the property, not null */ public List> getAddressesList() { return addressesList; } /** * Sets the addressesList. * @param addressesList the new value of the property, not null */ public void setAddressesList(List> addressesList) { JodaBeanUtils.notNull(addressesList, "addressesList"); this.addressesList.clear(); this.addressesList.addAll(addressesList); } /** * Gets the the {@code addressesList} property. * @return the property, not null */ public Property>> addressesList() { return metaBean().addressesList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the mainAddress. * @return the value of the property */ public Address getMainAddress() { return mainAddress; } /** * Sets the mainAddress. * @param mainAddress the new value of the property */ public void setMainAddress(Address mainAddress) { this.mainAddress = mainAddress; } /** * Gets the the {@code mainAddress} property. * @return the property, not null */ public Property
mainAddress() { return metaBean().mainAddress().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the propDefAnnotationSecondDeprecated. * @return the value of the property, not null * @deprecated Deprecated */ @Deprecated public FlexiBean getPropDefAnnotationSecondDeprecated() { return propDefAnnotationSecondDeprecated; } /** * Sets the propDefAnnotationSecondDeprecated. * @param propDefAnnotationSecondDeprecated the new value of the property, not null * @deprecated Deprecated */ @Deprecated public void setPropDefAnnotationSecondDeprecated(FlexiBean propDefAnnotationSecondDeprecated) { JodaBeanUtils.notNull(propDefAnnotationSecondDeprecated, "propDefAnnotationSecondDeprecated"); this.propDefAnnotationSecondDeprecated.clear(); this.propDefAnnotationSecondDeprecated.putAll(propDefAnnotationSecondDeprecated); } /** * Gets the the {@code propDefAnnotationSecondDeprecated} property. * @return the property, not null * @deprecated Deprecated */ @Deprecated public Property propDefAnnotationSecondDeprecated() { return metaBean().propDefAnnotationSecondDeprecated().createProperty(this); } //----------------------------------------------------------------------- /** * Sets the propDefAnnotationSecondManual. * @param propDefAnnotationSecondManual the new value of the property */ public void setPropDefAnnotationSecondManual(Map propDefAnnotationSecondManual) { this.propDefAnnotationSecondManual = propDefAnnotationSecondManual; } /** * Gets the the {@code propDefAnnotationSecondManual} property. * @return the property, not null */ public Property> propDefAnnotationSecondManual() { return metaBean().propDefAnnotationSecondManual().createProperty(this); } //----------------------------------------------------------------------- @Override public SimplePerson clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimplePerson other = (SimplePerson) obj; return JodaBeanUtils.equal(this.getForename(), other.getForename()) && JodaBeanUtils.equal(this.getSurname(), other.getSurname()) && (this.getNumberOfCars() == other.getNumberOfCars()) && JodaBeanUtils.equal(this.getAddressList(), other.getAddressList()) && JodaBeanUtils.equal(this.getOtherAddressMap(), other.getOtherAddressMap()) && JodaBeanUtils.equal(this.getAddressesList(), other.getAddressesList()) && JodaBeanUtils.equal(this.getMainAddress(), other.getMainAddress()) && JodaBeanUtils.equal(this.getPropDefAnnotationSecondDeprecated(), other.getPropDefAnnotationSecondDeprecated()) && JodaBeanUtils.equal(this.getPropDefAnnotationSecondManual(), other.getPropDefAnnotationSecondManual()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getForename()); hash = hash * 31 + JodaBeanUtils.hashCode(getSurname()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberOfCars()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressList()); hash = hash * 31 + JodaBeanUtils.hashCode(getOtherAddressMap()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressesList()); hash = hash * 31 + JodaBeanUtils.hashCode(getMainAddress()); hash = hash * 31 + JodaBeanUtils.hashCode(getPropDefAnnotationSecondDeprecated()); hash = hash * 31 + JodaBeanUtils.hashCode(getPropDefAnnotationSecondManual()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(320); buf.append("SimplePerson{"); buf.append("forename").append('=').append(JodaBeanUtils.toString(getForename())).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(getSurname())).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(getNumberOfCars())).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(getAddressList())).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(getOtherAddressMap())).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(getAddressesList())).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(getMainAddress())).append(',').append(' '); buf.append("propDefAnnotationSecondDeprecated").append('=').append(JodaBeanUtils.toString(getPropDefAnnotationSecondDeprecated())).append(',').append(' '); buf.append("propDefAnnotationSecondManual").append('=').append(JodaBeanUtils.toString(getPropDefAnnotationSecondManual())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimplePerson}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofReadWrite( this, "forename", SimplePerson.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofReadWrite( this, "surname", SimplePerson.class, String.class); /** * The meta-property for the {@code numberOfCars} property. */ private final MetaProperty numberOfCars = DirectMetaProperty.ofReadWrite( this, "numberOfCars", SimplePerson.class, Integer.TYPE); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofReadWrite( this, "addressList", SimplePerson.class, (Class) List.class); /** * The meta-property for the {@code otherAddressMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> otherAddressMap = DirectMetaProperty.ofReadWrite( this, "otherAddressMap", SimplePerson.class, (Class) Map.class); /** * The meta-property for the {@code addressesList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> addressesList = DirectMetaProperty.ofReadWrite( this, "addressesList", SimplePerson.class, (Class) List.class); /** * The meta-property for the {@code mainAddress} property. */ private final MetaProperty
mainAddress = DirectMetaProperty.ofReadWrite( this, "mainAddress", SimplePerson.class, Address.class); /** * The meta-property for the {@code propDefAnnotationSecondDeprecated} property. */ private final MetaProperty propDefAnnotationSecondDeprecated = DirectMetaProperty.ofReadWrite( this, "propDefAnnotationSecondDeprecated", SimplePerson.class, FlexiBean.class); /** * The meta-property for the {@code propDefAnnotationSecondManual} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> propDefAnnotationSecondManual = DirectMetaProperty.ofReadWrite( this, "propDefAnnotationSecondManual", SimplePerson.class, (Class) Map.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "numberOfCars", "addressList", "otherAddressMap", "addressesList", "mainAddress", "propDefAnnotationSecondDeprecated", "propDefAnnotationSecondManual"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; case 1897330136: // propDefAnnotationSecondDeprecated return this.propDefAnnotationSecondDeprecated; case 1276990059: // propDefAnnotationSecondManual return this.propDefAnnotationSecondManual; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new SimplePerson()); } @Override public Class beanType() { return SimplePerson.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public MetaProperty surname() { return surname; } /** * The meta-property for the {@code numberOfCars} property. * @return the meta-property, not null */ public MetaProperty numberOfCars() { return numberOfCars; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public MetaProperty> addressList() { return addressList; } /** * The meta-property for the {@code otherAddressMap} property. * @return the meta-property, not null */ public MetaProperty> otherAddressMap() { return otherAddressMap; } /** * The meta-property for the {@code addressesList} property. * @return the meta-property, not null */ public MetaProperty>> addressesList() { return addressesList; } /** * The meta-property for the {@code mainAddress} property. * @return the meta-property, not null */ public MetaProperty
mainAddress() { return mainAddress; } /** * The meta-property for the {@code propDefAnnotationSecondDeprecated} property. * @return the meta-property, not null * @deprecated Deprecated */ @Deprecated public MetaProperty propDefAnnotationSecondDeprecated() { return propDefAnnotationSecondDeprecated; } /** * The meta-property for the {@code propDefAnnotationSecondManual} property. * @return the meta-property, not null */ public MetaProperty> propDefAnnotationSecondManual() { return propDefAnnotationSecondManual; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((SimplePerson) bean).getForename(); case -1852993317: // surname return ((SimplePerson) bean).getSurname(); case 926656063: // numberOfCars return ((SimplePerson) bean).getNumberOfCars(); case -1377524046: // addressList return ((SimplePerson) bean).getAddressList(); case 1368089592: // otherAddressMap return ((SimplePerson) bean).getOtherAddressMap(); case -226885792: // addressesList return ((SimplePerson) bean).getAddressesList(); case -2032731141: // mainAddress return ((SimplePerson) bean).getMainAddress(); case 1897330136: // propDefAnnotationSecondDeprecated return ((SimplePerson) bean).getPropDefAnnotationSecondDeprecated(); case 1276990059: // propDefAnnotationSecondManual return ((SimplePerson) bean).getPropDefAnnotationSecondManual(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename ((SimplePerson) bean).setForename((String) newValue); return; case -1852993317: // surname ((SimplePerson) bean).setSurname((String) newValue); return; case 926656063: // numberOfCars ((SimplePerson) bean).setNumberOfCars((Integer) newValue); return; case -1377524046: // addressList ((SimplePerson) bean).setAddressList((List
) newValue); return; case 1368089592: // otherAddressMap ((SimplePerson) bean).setOtherAddressMap((Map) newValue); return; case -226885792: // addressesList ((SimplePerson) bean).setAddressesList((List>) newValue); return; case -2032731141: // mainAddress ((SimplePerson) bean).setMainAddress((Address) newValue); return; case 1897330136: // propDefAnnotationSecondDeprecated ((SimplePerson) bean).setPropDefAnnotationSecondDeprecated((FlexiBean) newValue); return; case 1276990059: // propDefAnnotationSecondManual ((SimplePerson) bean).setPropDefAnnotationSecondManual((Map) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((SimplePerson) bean).addressList, "addressList"); JodaBeanUtils.notNull(((SimplePerson) bean).otherAddressMap, "otherAddressMap"); JodaBeanUtils.notNull(((SimplePerson) bean).addressesList, "addressesList"); JodaBeanUtils.notNull(((SimplePerson) bean).propDefAnnotationSecondDeprecated, "propDefAnnotationSecondDeprecated"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SimplePersonWithBuilderFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public final class SimplePersonWithBuilderFinal implements Cloneable, Bean { /** The forename. */ @PropertyDefinition private String forename; /** The surname. */ @PropertyDefinition(validate = "notNull") private final String surname; /** The number of cars. */ @PropertyDefinition private transient int numberOfCars; @PropertyDefinition private final List
addressList = new ArrayList<>(); @PropertyDefinition(validate = "notNull") private final Map otherAddressMap = new HashMap<>(); @PropertyDefinition(validate = "notNull") private final List> addressesList = new ArrayList<>(); @PropertyDefinition private Address mainAddress; @PropertyDefinition private String[] tags; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimplePersonWithBuilderFinal}. * @return the meta-bean, not null */ public static SimplePersonWithBuilderFinal.Meta meta() { return SimplePersonWithBuilderFinal.Meta.INSTANCE; } static { MetaBean.register(SimplePersonWithBuilderFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static SimplePersonWithBuilderFinal.Builder builder() { return new SimplePersonWithBuilderFinal.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ private SimplePersonWithBuilderFinal(SimplePersonWithBuilderFinal.Builder builder) { JodaBeanUtils.notNull(builder.surname, "surname"); JodaBeanUtils.notNull(builder.addressList, "addressList"); JodaBeanUtils.notNull(builder.otherAddressMap, "otherAddressMap"); JodaBeanUtils.notNull(builder.addressesList, "addressesList"); this.forename = builder.forename; this.surname = builder.surname; this.numberOfCars = builder.numberOfCars; this.addressList.addAll(builder.addressList); this.otherAddressMap.putAll(builder.otherAddressMap); this.addressesList.addAll(builder.addressesList); this.mainAddress = builder.mainAddress; this.tags = builder.tags; } @Override public SimplePersonWithBuilderFinal.Meta metaBean() { return SimplePersonWithBuilderFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } /** * Sets the forename. * @param forename the new value of the property */ public void setForename(String forename) { this.forename = forename; } /** * Gets the the {@code forename} property. * @return the property, not null */ public Property forename() { return metaBean().forename().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property, not null */ public String getSurname() { return surname; } /** * Gets the the {@code surname} property. * @return the property, not null */ public Property surname() { return metaBean().surname().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the number of cars. * @return the value of the property */ public int getNumberOfCars() { return numberOfCars; } /** * Sets the number of cars. * @param numberOfCars the new value of the property */ public void setNumberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; } /** * Gets the the {@code numberOfCars} property. * @return the property, not null */ public Property numberOfCars() { return metaBean().numberOfCars().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressList. * @return the value of the property, not null */ public List
getAddressList() { return addressList; } /** * Sets the addressList. * @param addressList the new value of the property, not null */ public void setAddressList(List
addressList) { JodaBeanUtils.notNull(addressList, "addressList"); this.addressList.clear(); this.addressList.addAll(addressList); } /** * Gets the the {@code addressList} property. * @return the property, not null */ public Property> addressList() { return metaBean().addressList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the otherAddressMap. * @return the value of the property, not null */ public Map getOtherAddressMap() { return otherAddressMap; } /** * Sets the otherAddressMap. * @param otherAddressMap the new value of the property, not null */ public void setOtherAddressMap(Map otherAddressMap) { JodaBeanUtils.notNull(otherAddressMap, "otherAddressMap"); this.otherAddressMap.clear(); this.otherAddressMap.putAll(otherAddressMap); } /** * Gets the the {@code otherAddressMap} property. * @return the property, not null */ public Property> otherAddressMap() { return metaBean().otherAddressMap().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressesList. * @return the value of the property, not null */ public List> getAddressesList() { return addressesList; } /** * Sets the addressesList. * @param addressesList the new value of the property, not null */ public void setAddressesList(List> addressesList) { JodaBeanUtils.notNull(addressesList, "addressesList"); this.addressesList.clear(); this.addressesList.addAll(addressesList); } /** * Gets the the {@code addressesList} property. * @return the property, not null */ public Property>> addressesList() { return metaBean().addressesList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the mainAddress. * @return the value of the property */ public Address getMainAddress() { return mainAddress; } /** * Sets the mainAddress. * @param mainAddress the new value of the property */ public void setMainAddress(Address mainAddress) { this.mainAddress = mainAddress; } /** * Gets the the {@code mainAddress} property. * @return the property, not null */ public Property
mainAddress() { return metaBean().mainAddress().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the tags. * @return the value of the property */ public String[] getTags() { return tags; } /** * Sets the tags. * @param tags the new value of the property */ public void setTags(String[] tags) { this.tags = tags; } /** * Gets the the {@code tags} property. * @return the property, not null */ public Property tags() { return metaBean().tags().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public SimplePersonWithBuilderFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimplePersonWithBuilderFinal other = (SimplePersonWithBuilderFinal) obj; return JodaBeanUtils.equal(this.getForename(), other.getForename()) && JodaBeanUtils.equal(this.getSurname(), other.getSurname()) && (this.getNumberOfCars() == other.getNumberOfCars()) && JodaBeanUtils.equal(this.getAddressList(), other.getAddressList()) && JodaBeanUtils.equal(this.getOtherAddressMap(), other.getOtherAddressMap()) && JodaBeanUtils.equal(this.getAddressesList(), other.getAddressesList()) && JodaBeanUtils.equal(this.getMainAddress(), other.getMainAddress()) && JodaBeanUtils.equal(this.getTags(), other.getTags()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getForename()); hash = hash * 31 + JodaBeanUtils.hashCode(getSurname()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberOfCars()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressList()); hash = hash * 31 + JodaBeanUtils.hashCode(getOtherAddressMap()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressesList()); hash = hash * 31 + JodaBeanUtils.hashCode(getMainAddress()); hash = hash * 31 + JodaBeanUtils.hashCode(getTags()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("SimplePersonWithBuilderFinal{"); buf.append("forename").append('=').append(JodaBeanUtils.toString(getForename())).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(getSurname())).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(getNumberOfCars())).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(getAddressList())).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(getOtherAddressMap())).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(getAddressesList())).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(getMainAddress())).append(',').append(' '); buf.append("tags").append('=').append(JodaBeanUtils.toString(getTags())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimplePersonWithBuilderFinal}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofReadWrite( this, "forename", SimplePersonWithBuilderFinal.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofReadOnlyBuildable( this, "surname", SimplePersonWithBuilderFinal.class, String.class); /** * The meta-property for the {@code numberOfCars} property. */ private final MetaProperty numberOfCars = DirectMetaProperty.ofReadWrite( this, "numberOfCars", SimplePersonWithBuilderFinal.class, Integer.TYPE); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofReadWrite( this, "addressList", SimplePersonWithBuilderFinal.class, (Class) List.class); /** * The meta-property for the {@code otherAddressMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> otherAddressMap = DirectMetaProperty.ofReadWrite( this, "otherAddressMap", SimplePersonWithBuilderFinal.class, (Class) Map.class); /** * The meta-property for the {@code addressesList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> addressesList = DirectMetaProperty.ofReadWrite( this, "addressesList", SimplePersonWithBuilderFinal.class, (Class) List.class); /** * The meta-property for the {@code mainAddress} property. */ private final MetaProperty
mainAddress = DirectMetaProperty.ofReadWrite( this, "mainAddress", SimplePersonWithBuilderFinal.class, Address.class); /** * The meta-property for the {@code tags} property. */ private final MetaProperty tags = DirectMetaProperty.ofReadWrite( this, "tags", SimplePersonWithBuilderFinal.class, String[].class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "numberOfCars", "addressList", "otherAddressMap", "addressesList", "mainAddress", "tags"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; case 3552281: // tags return this.tags; } return super.metaPropertyGet(propertyName); } @Override public SimplePersonWithBuilderFinal.Builder builder() { return new SimplePersonWithBuilderFinal.Builder(); } @Override public Class beanType() { return SimplePersonWithBuilderFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public MetaProperty surname() { return surname; } /** * The meta-property for the {@code numberOfCars} property. * @return the meta-property, not null */ public MetaProperty numberOfCars() { return numberOfCars; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public MetaProperty> addressList() { return addressList; } /** * The meta-property for the {@code otherAddressMap} property. * @return the meta-property, not null */ public MetaProperty> otherAddressMap() { return otherAddressMap; } /** * The meta-property for the {@code addressesList} property. * @return the meta-property, not null */ public MetaProperty>> addressesList() { return addressesList; } /** * The meta-property for the {@code mainAddress} property. * @return the meta-property, not null */ public MetaProperty
mainAddress() { return mainAddress; } /** * The meta-property for the {@code tags} property. * @return the meta-property, not null */ public MetaProperty tags() { return tags; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((SimplePersonWithBuilderFinal) bean).getForename(); case -1852993317: // surname return ((SimplePersonWithBuilderFinal) bean).getSurname(); case 926656063: // numberOfCars return ((SimplePersonWithBuilderFinal) bean).getNumberOfCars(); case -1377524046: // addressList return ((SimplePersonWithBuilderFinal) bean).getAddressList(); case 1368089592: // otherAddressMap return ((SimplePersonWithBuilderFinal) bean).getOtherAddressMap(); case -226885792: // addressesList return ((SimplePersonWithBuilderFinal) bean).getAddressesList(); case -2032731141: // mainAddress return ((SimplePersonWithBuilderFinal) bean).getMainAddress(); case 3552281: // tags return ((SimplePersonWithBuilderFinal) bean).getTags(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename ((SimplePersonWithBuilderFinal) bean).setForename((String) newValue); return; case -1852993317: // surname if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: surname"); case 926656063: // numberOfCars ((SimplePersonWithBuilderFinal) bean).setNumberOfCars((Integer) newValue); return; case -1377524046: // addressList ((SimplePersonWithBuilderFinal) bean).setAddressList((List
) newValue); return; case 1368089592: // otherAddressMap ((SimplePersonWithBuilderFinal) bean).setOtherAddressMap((Map) newValue); return; case -226885792: // addressesList ((SimplePersonWithBuilderFinal) bean).setAddressesList((List>) newValue); return; case -2032731141: // mainAddress ((SimplePersonWithBuilderFinal) bean).setMainAddress((Address) newValue); return; case 3552281: // tags ((SimplePersonWithBuilderFinal) bean).setTags((String[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((SimplePersonWithBuilderFinal) bean).surname, "surname"); JodaBeanUtils.notNull(((SimplePersonWithBuilderFinal) bean).addressList, "addressList"); JodaBeanUtils.notNull(((SimplePersonWithBuilderFinal) bean).otherAddressMap, "otherAddressMap"); JodaBeanUtils.notNull(((SimplePersonWithBuilderFinal) bean).addressesList, "addressesList"); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code SimplePersonWithBuilderFinal}. */ public static final class Builder extends DirectFieldsBeanBuilder { private String forename; private String surname; private int numberOfCars; private List
addressList = ImmutableList.of(); private Map otherAddressMap = ImmutableMap.of(); private List> addressesList = ImmutableList.of(); private Address mainAddress; private String[] tags; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(SimplePersonWithBuilderFinal beanToCopy) { this.forename = beanToCopy.getForename(); this.surname = beanToCopy.getSurname(); this.numberOfCars = beanToCopy.getNumberOfCars(); this.addressList = ImmutableList.copyOf(beanToCopy.getAddressList()); this.otherAddressMap = ImmutableMap.copyOf(beanToCopy.getOtherAddressMap()); this.addressesList = ImmutableList.copyOf(beanToCopy.getAddressesList()); this.mainAddress = beanToCopy.getMainAddress(); this.tags = (beanToCopy.getTags() != null ? beanToCopy.getTags().clone() : null); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; case 3552281: // tags return this.tags; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 467061063: // forename this.forename = (String) newValue; break; case -1852993317: // surname this.surname = (String) newValue; break; case 926656063: // numberOfCars this.numberOfCars = (Integer) newValue; break; case -1377524046: // addressList this.addressList = (List
) newValue; break; case 1368089592: // otherAddressMap this.otherAddressMap = (Map) newValue; break; case -226885792: // addressesList this.addressesList = (List>) newValue; break; case -2032731141: // mainAddress this.mainAddress = (Address) newValue; break; case 3552281: // tags this.tags = (String[]) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public SimplePersonWithBuilderFinal build() { return new SimplePersonWithBuilderFinal(this); } //----------------------------------------------------------------------- /** * Sets the forename. * @param forename the new value * @return this, for chaining, not null */ public Builder forename(String forename) { this.forename = forename; return this; } /** * Sets the surname. * @param surname the new value, not null * @return this, for chaining, not null */ public Builder surname(String surname) { JodaBeanUtils.notNull(surname, "surname"); this.surname = surname; return this; } /** * Sets the number of cars. * @param numberOfCars the new value * @return this, for chaining, not null */ public Builder numberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; return this; } /** * Sets the addressList. * @param addressList the new value, not null * @return this, for chaining, not null */ public Builder addressList(List
addressList) { JodaBeanUtils.notNull(addressList, "addressList"); this.addressList = addressList; return this; } /** * Sets the {@code addressList} property in the builder * from an array of objects. * @param addressList the new value, not null * @return this, for chaining, not null */ public Builder addressList(Address... addressList) { return addressList(ImmutableList.copyOf(addressList)); } /** * Sets the otherAddressMap. * @param otherAddressMap the new value, not null * @return this, for chaining, not null */ public Builder otherAddressMap(Map otherAddressMap) { JodaBeanUtils.notNull(otherAddressMap, "otherAddressMap"); this.otherAddressMap = otherAddressMap; return this; } /** * Sets the addressesList. * @param addressesList the new value, not null * @return this, for chaining, not null */ public Builder addressesList(List> addressesList) { JodaBeanUtils.notNull(addressesList, "addressesList"); this.addressesList = addressesList; return this; } /** * Sets the {@code addressesList} property in the builder * from an array of objects. * @param addressesList the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder addressesList(List
... addressesList) { return addressesList(ImmutableList.copyOf(addressesList)); } /** * Sets the mainAddress. * @param mainAddress the new value * @return this, for chaining, not null */ public Builder mainAddress(Address mainAddress) { this.mainAddress = mainAddress; return this; } /** * Sets the tags. * @param tags the new value * @return this, for chaining, not null */ public Builder tags(String... tags) { this.tags = tags; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(288); buf.append("SimplePersonWithBuilderFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(numberOfCars)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(otherAddressMap)).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(addressesList)).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(mainAddress)).append(',').append(' '); buf.append("tags").append('=').append(JodaBeanUtils.toString(tags)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SimplePersonWithBuilderNonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public class SimplePersonWithBuilderNonFinal implements Cloneable, Bean { /** The forename. */ @PropertyDefinition private String forename; /** The surname. */ @PropertyDefinition(validate = "notNull") private final String surname; /** The number of cars. */ @PropertyDefinition private transient int numberOfCars; @PropertyDefinition private final List
addressList = new ArrayList<>(); @PropertyDefinition(validate = "notNull") private final Map otherAddressMap = new HashMap<>(); @PropertyDefinition(validate = "notNull") private final List> addressesList = new ArrayList<>(); @PropertyDefinition private Address mainAddress; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimplePersonWithBuilderNonFinal}. * @return the meta-bean, not null */ public static SimplePersonWithBuilderNonFinal.Meta meta() { return SimplePersonWithBuilderNonFinal.Meta.INSTANCE; } static { MetaBean.register(SimplePersonWithBuilderNonFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static SimplePersonWithBuilderNonFinal.Builder builder() { return new SimplePersonWithBuilderNonFinal.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected SimplePersonWithBuilderNonFinal(SimplePersonWithBuilderNonFinal.Builder builder) { JodaBeanUtils.notNull(builder.surname, "surname"); JodaBeanUtils.notNull(builder.addressList, "addressList"); JodaBeanUtils.notNull(builder.otherAddressMap, "otherAddressMap"); JodaBeanUtils.notNull(builder.addressesList, "addressesList"); this.forename = builder.forename; this.surname = builder.surname; this.numberOfCars = builder.numberOfCars; this.addressList.addAll(builder.addressList); this.otherAddressMap.putAll(builder.otherAddressMap); this.addressesList.addAll(builder.addressesList); this.mainAddress = builder.mainAddress; } @Override public SimplePersonWithBuilderNonFinal.Meta metaBean() { return SimplePersonWithBuilderNonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename. * @return the value of the property */ public String getForename() { return forename; } /** * Sets the forename. * @param forename the new value of the property */ public void setForename(String forename) { this.forename = forename; } /** * Gets the the {@code forename} property. * @return the property, not null */ public final Property forename() { return metaBean().forename().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property, not null */ public String getSurname() { return surname; } /** * Gets the the {@code surname} property. * @return the property, not null */ public final Property surname() { return metaBean().surname().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the number of cars. * @return the value of the property */ public int getNumberOfCars() { return numberOfCars; } /** * Sets the number of cars. * @param numberOfCars the new value of the property */ public void setNumberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; } /** * Gets the the {@code numberOfCars} property. * @return the property, not null */ public final Property numberOfCars() { return metaBean().numberOfCars().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressList. * @return the value of the property, not null */ public List
getAddressList() { return addressList; } /** * Sets the addressList. * @param addressList the new value of the property, not null */ public void setAddressList(List
addressList) { JodaBeanUtils.notNull(addressList, "addressList"); this.addressList.clear(); this.addressList.addAll(addressList); } /** * Gets the the {@code addressList} property. * @return the property, not null */ public final Property> addressList() { return metaBean().addressList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the otherAddressMap. * @return the value of the property, not null */ public Map getOtherAddressMap() { return otherAddressMap; } /** * Sets the otherAddressMap. * @param otherAddressMap the new value of the property, not null */ public void setOtherAddressMap(Map otherAddressMap) { JodaBeanUtils.notNull(otherAddressMap, "otherAddressMap"); this.otherAddressMap.clear(); this.otherAddressMap.putAll(otherAddressMap); } /** * Gets the the {@code otherAddressMap} property. * @return the property, not null */ public final Property> otherAddressMap() { return metaBean().otherAddressMap().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the addressesList. * @return the value of the property, not null */ public List> getAddressesList() { return addressesList; } /** * Sets the addressesList. * @param addressesList the new value of the property, not null */ public void setAddressesList(List> addressesList) { JodaBeanUtils.notNull(addressesList, "addressesList"); this.addressesList.clear(); this.addressesList.addAll(addressesList); } /** * Gets the the {@code addressesList} property. * @return the property, not null */ public final Property>> addressesList() { return metaBean().addressesList().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the mainAddress. * @return the value of the property */ public Address getMainAddress() { return mainAddress; } /** * Sets the mainAddress. * @param mainAddress the new value of the property */ public void setMainAddress(Address mainAddress) { this.mainAddress = mainAddress; } /** * Gets the the {@code mainAddress} property. * @return the property, not null */ public final Property
mainAddress() { return metaBean().mainAddress().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder(this); } @Override public SimplePersonWithBuilderNonFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimplePersonWithBuilderNonFinal other = (SimplePersonWithBuilderNonFinal) obj; return JodaBeanUtils.equal(this.getForename(), other.getForename()) && JodaBeanUtils.equal(this.getSurname(), other.getSurname()) && (this.getNumberOfCars() == other.getNumberOfCars()) && JodaBeanUtils.equal(this.getAddressList(), other.getAddressList()) && JodaBeanUtils.equal(this.getOtherAddressMap(), other.getOtherAddressMap()) && JodaBeanUtils.equal(this.getAddressesList(), other.getAddressesList()) && JodaBeanUtils.equal(this.getMainAddress(), other.getMainAddress()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getForename()); hash = hash * 31 + JodaBeanUtils.hashCode(getSurname()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberOfCars()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressList()); hash = hash * 31 + JodaBeanUtils.hashCode(getOtherAddressMap()); hash = hash * 31 + JodaBeanUtils.hashCode(getAddressesList()); hash = hash * 31 + JodaBeanUtils.hashCode(getMainAddress()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("SimplePersonWithBuilderNonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(getForename())).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(getSurname())).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(getNumberOfCars())).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(getAddressList())).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(getOtherAddressMap())).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(getAddressesList())).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(getMainAddress())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimplePersonWithBuilderNonFinal}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename} property. */ private final MetaProperty forename = DirectMetaProperty.ofReadWrite( this, "forename", SimplePersonWithBuilderNonFinal.class, String.class); /** * The meta-property for the {@code surname} property. */ private final MetaProperty surname = DirectMetaProperty.ofReadOnlyBuildable( this, "surname", SimplePersonWithBuilderNonFinal.class, String.class); /** * The meta-property for the {@code numberOfCars} property. */ private final MetaProperty numberOfCars = DirectMetaProperty.ofReadWrite( this, "numberOfCars", SimplePersonWithBuilderNonFinal.class, Integer.TYPE); /** * The meta-property for the {@code addressList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> addressList = DirectMetaProperty.ofReadWrite( this, "addressList", SimplePersonWithBuilderNonFinal.class, (Class) List.class); /** * The meta-property for the {@code otherAddressMap} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> otherAddressMap = DirectMetaProperty.ofReadWrite( this, "otherAddressMap", SimplePersonWithBuilderNonFinal.class, (Class) Map.class); /** * The meta-property for the {@code addressesList} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty>> addressesList = DirectMetaProperty.ofReadWrite( this, "addressesList", SimplePersonWithBuilderNonFinal.class, (Class) List.class); /** * The meta-property for the {@code mainAddress} property. */ private final MetaProperty
mainAddress = DirectMetaProperty.ofReadWrite( this, "mainAddress", SimplePersonWithBuilderNonFinal.class, Address.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename", "surname", "numberOfCars", "addressList", "otherAddressMap", "addressesList", "mainAddress"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; } return super.metaPropertyGet(propertyName); } @Override public SimplePersonWithBuilderNonFinal.Builder builder() { return new SimplePersonWithBuilderNonFinal.Builder(); } @Override public Class beanType() { return SimplePersonWithBuilderNonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename} property. * @return the meta-property, not null */ public final MetaProperty forename() { return forename; } /** * The meta-property for the {@code surname} property. * @return the meta-property, not null */ public final MetaProperty surname() { return surname; } /** * The meta-property for the {@code numberOfCars} property. * @return the meta-property, not null */ public final MetaProperty numberOfCars() { return numberOfCars; } /** * The meta-property for the {@code addressList} property. * @return the meta-property, not null */ public final MetaProperty> addressList() { return addressList; } /** * The meta-property for the {@code otherAddressMap} property. * @return the meta-property, not null */ public final MetaProperty> otherAddressMap() { return otherAddressMap; } /** * The meta-property for the {@code addressesList} property. * @return the meta-property, not null */ public final MetaProperty>> addressesList() { return addressesList; } /** * The meta-property for the {@code mainAddress} property. * @return the meta-property, not null */ public final MetaProperty
mainAddress() { return mainAddress; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename return ((SimplePersonWithBuilderNonFinal) bean).getForename(); case -1852993317: // surname return ((SimplePersonWithBuilderNonFinal) bean).getSurname(); case 926656063: // numberOfCars return ((SimplePersonWithBuilderNonFinal) bean).getNumberOfCars(); case -1377524046: // addressList return ((SimplePersonWithBuilderNonFinal) bean).getAddressList(); case 1368089592: // otherAddressMap return ((SimplePersonWithBuilderNonFinal) bean).getOtherAddressMap(); case -226885792: // addressesList return ((SimplePersonWithBuilderNonFinal) bean).getAddressesList(); case -2032731141: // mainAddress return ((SimplePersonWithBuilderNonFinal) bean).getMainAddress(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 467061063: // forename ((SimplePersonWithBuilderNonFinal) bean).setForename((String) newValue); return; case -1852993317: // surname if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: surname"); case 926656063: // numberOfCars ((SimplePersonWithBuilderNonFinal) bean).setNumberOfCars((Integer) newValue); return; case -1377524046: // addressList ((SimplePersonWithBuilderNonFinal) bean).setAddressList((List
) newValue); return; case 1368089592: // otherAddressMap ((SimplePersonWithBuilderNonFinal) bean).setOtherAddressMap((Map) newValue); return; case -226885792: // addressesList ((SimplePersonWithBuilderNonFinal) bean).setAddressesList((List>) newValue); return; case -2032731141: // mainAddress ((SimplePersonWithBuilderNonFinal) bean).setMainAddress((Address) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((SimplePersonWithBuilderNonFinal) bean).surname, "surname"); JodaBeanUtils.notNull(((SimplePersonWithBuilderNonFinal) bean).addressList, "addressList"); JodaBeanUtils.notNull(((SimplePersonWithBuilderNonFinal) bean).otherAddressMap, "otherAddressMap"); JodaBeanUtils.notNull(((SimplePersonWithBuilderNonFinal) bean).addressesList, "addressesList"); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code SimplePersonWithBuilderNonFinal}. */ public static class Builder extends DirectFieldsBeanBuilder { private String forename; private String surname; private int numberOfCars; private List
addressList = ImmutableList.of(); private Map otherAddressMap = ImmutableMap.of(); private List> addressesList = ImmutableList.of(); private Address mainAddress; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(SimplePersonWithBuilderNonFinal beanToCopy) { this.forename = beanToCopy.getForename(); this.surname = beanToCopy.getSurname(); this.numberOfCars = beanToCopy.getNumberOfCars(); this.addressList = ImmutableList.copyOf(beanToCopy.getAddressList()); this.otherAddressMap = ImmutableMap.copyOf(beanToCopy.getOtherAddressMap()); this.addressesList = ImmutableList.copyOf(beanToCopy.getAddressesList()); this.mainAddress = beanToCopy.getMainAddress(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 467061063: // forename return this.forename; case -1852993317: // surname return this.surname; case 926656063: // numberOfCars return this.numberOfCars; case -1377524046: // addressList return this.addressList; case 1368089592: // otherAddressMap return this.otherAddressMap; case -226885792: // addressesList return this.addressesList; case -2032731141: // mainAddress return this.mainAddress; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 467061063: // forename this.forename = (String) newValue; break; case -1852993317: // surname this.surname = (String) newValue; break; case 926656063: // numberOfCars this.numberOfCars = (Integer) newValue; break; case -1377524046: // addressList this.addressList = (List
) newValue; break; case 1368089592: // otherAddressMap this.otherAddressMap = (Map) newValue; break; case -226885792: // addressesList this.addressesList = (List>) newValue; break; case -2032731141: // mainAddress this.mainAddress = (Address) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public SimplePersonWithBuilderNonFinal build() { return new SimplePersonWithBuilderNonFinal(this); } //----------------------------------------------------------------------- /** * Sets the forename. * @param forename the new value * @return this, for chaining, not null */ public Builder forename(String forename) { this.forename = forename; return this; } /** * Sets the surname. * @param surname the new value, not null * @return this, for chaining, not null */ public Builder surname(String surname) { JodaBeanUtils.notNull(surname, "surname"); this.surname = surname; return this; } /** * Sets the number of cars. * @param numberOfCars the new value * @return this, for chaining, not null */ public Builder numberOfCars(int numberOfCars) { this.numberOfCars = numberOfCars; return this; } /** * Sets the addressList. * @param addressList the new value, not null * @return this, for chaining, not null */ public Builder addressList(List
addressList) { JodaBeanUtils.notNull(addressList, "addressList"); this.addressList = addressList; return this; } /** * Sets the {@code addressList} property in the builder * from an array of objects. * @param addressList the new value, not null * @return this, for chaining, not null */ public Builder addressList(Address... addressList) { return addressList(ImmutableList.copyOf(addressList)); } /** * Sets the otherAddressMap. * @param otherAddressMap the new value, not null * @return this, for chaining, not null */ public Builder otherAddressMap(Map otherAddressMap) { JodaBeanUtils.notNull(otherAddressMap, "otherAddressMap"); this.otherAddressMap = otherAddressMap; return this; } /** * Sets the addressesList. * @param addressesList the new value, not null * @return this, for chaining, not null */ public Builder addressesList(List> addressesList) { JodaBeanUtils.notNull(addressesList, "addressesList"); this.addressesList = addressesList; return this; } /** * Sets the {@code addressesList} property in the builder * from an array of objects. * @param addressesList the new value, not null * @return this, for chaining, not null */ @SafeVarargs public final Builder addressesList(List
... addressesList) { return addressesList(ImmutableList.copyOf(addressesList)); } /** * Sets the mainAddress. * @param mainAddress the new value * @return this, for chaining, not null */ public Builder mainAddress(Address mainAddress) { this.mainAddress = mainAddress; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(256); buf.append("SimplePersonWithBuilderNonFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename").append('=').append(JodaBeanUtils.toString(forename)).append(',').append(' '); buf.append("surname").append('=').append(JodaBeanUtils.toString(surname)).append(',').append(' '); buf.append("numberOfCars").append('=').append(JodaBeanUtils.toString(numberOfCars)).append(',').append(' '); buf.append("addressList").append('=').append(JodaBeanUtils.toString(addressList)).append(',').append(' '); buf.append("otherAddressMap").append('=').append(JodaBeanUtils.toString(otherAddressMap)).append(',').append(' '); buf.append("addressesList").append('=').append(JodaBeanUtils.toString(addressesList)).append(',').append(' '); buf.append("mainAddress").append('=').append(JodaBeanUtils.toString(mainAddress)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SimpleSubPersonWithBuilderFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public final class SimpleSubPersonWithBuilderFinal extends SimplePersonWithBuilderNonFinal { /** The middle name. */ @PropertyDefinition private String middleName; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimpleSubPersonWithBuilderFinal}. * @return the meta-bean, not null */ public static SimpleSubPersonWithBuilderFinal.Meta meta() { return SimpleSubPersonWithBuilderFinal.Meta.INSTANCE; } static { MetaBean.register(SimpleSubPersonWithBuilderFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static SimpleSubPersonWithBuilderFinal.Builder builder() { return new SimpleSubPersonWithBuilderFinal.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ private SimpleSubPersonWithBuilderFinal(SimpleSubPersonWithBuilderFinal.Builder builder) { super(builder); this.middleName = builder.middleName; } @Override public SimpleSubPersonWithBuilderFinal.Meta metaBean() { return SimpleSubPersonWithBuilderFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the middle name. * @return the value of the property */ public String getMiddleName() { return middleName; } /** * Sets the middle name. * @param middleName the new value of the property */ public void setMiddleName(String middleName) { this.middleName = middleName; } /** * Gets the the {@code middleName} property. * @return the property, not null */ public Property middleName() { return metaBean().middleName().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public SimpleSubPersonWithBuilderFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimpleSubPersonWithBuilderFinal other = (SimpleSubPersonWithBuilderFinal) obj; return JodaBeanUtils.equal(this.getMiddleName(), other.getMiddleName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getMiddleName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("SimpleSubPersonWithBuilderFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(getMiddleName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimpleSubPersonWithBuilderFinal}. */ public static final class Meta extends SimplePersonWithBuilderNonFinal.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code middleName} property. */ private final MetaProperty middleName = DirectMetaProperty.ofReadWrite( this, "middleName", SimpleSubPersonWithBuilderFinal.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "middleName"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; } return super.metaPropertyGet(propertyName); } @Override public SimpleSubPersonWithBuilderFinal.Builder builder() { return new SimpleSubPersonWithBuilderFinal.Builder(); } @Override public Class beanType() { return SimpleSubPersonWithBuilderFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code middleName} property. * @return the meta-property, not null */ public MetaProperty middleName() { return middleName; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -818219584: // middleName return ((SimpleSubPersonWithBuilderFinal) bean).getMiddleName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -818219584: // middleName ((SimpleSubPersonWithBuilderFinal) bean).setMiddleName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code SimpleSubPersonWithBuilderFinal}. */ public static final class Builder extends SimplePersonWithBuilderNonFinal.Builder { private String middleName; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(SimpleSubPersonWithBuilderFinal beanToCopy) { super(beanToCopy); this.middleName = beanToCopy.getMiddleName(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; default: return super.get(propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -818219584: // middleName this.middleName = (String) newValue; break; default: super.set(propertyName, newValue); break; } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public SimpleSubPersonWithBuilderFinal build() { return new SimpleSubPersonWithBuilderFinal(this); } //----------------------------------------------------------------------- /** * Sets the middle name. * @param middleName the new value * @return this, for chaining, not null */ public Builder middleName(String middleName) { this.middleName = middleName; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("SimpleSubPersonWithBuilderFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(middleName)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SimpleSubPersonWithBuilderNonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock person JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "public") public class SimpleSubPersonWithBuilderNonFinal extends SimplePersonWithBuilderNonFinal { /** The middle name. */ @PropertyDefinition private String middleName; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SimpleSubPersonWithBuilderNonFinal}. * @return the meta-bean, not null */ public static SimpleSubPersonWithBuilderNonFinal.Meta meta() { return SimpleSubPersonWithBuilderNonFinal.Meta.INSTANCE; } static { MetaBean.register(SimpleSubPersonWithBuilderNonFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @return the builder, not null */ public static SimpleSubPersonWithBuilderNonFinal.Builder builder() { return new SimpleSubPersonWithBuilderNonFinal.Builder(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected SimpleSubPersonWithBuilderNonFinal(SimpleSubPersonWithBuilderNonFinal.Builder builder) { super(builder); this.middleName = builder.middleName; } @Override public SimpleSubPersonWithBuilderNonFinal.Meta metaBean() { return SimpleSubPersonWithBuilderNonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the middle name. * @return the value of the property */ public String getMiddleName() { return middleName; } /** * Sets the middle name. * @param middleName the new value of the property */ public void setMiddleName(String middleName) { this.middleName = middleName; } /** * Gets the the {@code middleName} property. * @return the property, not null */ public final Property middleName() { return metaBean().middleName().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ @Override public Builder toBuilder() { return new Builder(this); } @Override public SimpleSubPersonWithBuilderNonFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SimpleSubPersonWithBuilderNonFinal other = (SimpleSubPersonWithBuilderNonFinal) obj; return JodaBeanUtils.equal(this.getMiddleName(), other.getMiddleName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getMiddleName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("SimpleSubPersonWithBuilderNonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(getMiddleName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SimpleSubPersonWithBuilderNonFinal}. */ public static class Meta extends SimplePersonWithBuilderNonFinal.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code middleName} property. */ private final MetaProperty middleName = DirectMetaProperty.ofReadWrite( this, "middleName", SimpleSubPersonWithBuilderNonFinal.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "middleName"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; } return super.metaPropertyGet(propertyName); } @Override public SimpleSubPersonWithBuilderNonFinal.Builder builder() { return new SimpleSubPersonWithBuilderNonFinal.Builder(); } @Override public Class beanType() { return SimpleSubPersonWithBuilderNonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code middleName} property. * @return the meta-property, not null */ public final MetaProperty middleName() { return middleName; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -818219584: // middleName return ((SimpleSubPersonWithBuilderNonFinal) bean).getMiddleName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -818219584: // middleName ((SimpleSubPersonWithBuilderNonFinal) bean).setMiddleName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code SimpleSubPersonWithBuilderNonFinal}. */ public static class Builder extends SimplePersonWithBuilderNonFinal.Builder { private String middleName; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(SimpleSubPersonWithBuilderNonFinal beanToCopy) { super(beanToCopy); this.middleName = beanToCopy.getMiddleName(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case -818219584: // middleName return this.middleName; default: return super.get(propertyName); } } @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case -818219584: // middleName this.middleName = (String) newValue; break; default: super.set(propertyName, newValue); break; } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public SimpleSubPersonWithBuilderNonFinal build() { return new SimpleSubPersonWithBuilderNonFinal(this); } //----------------------------------------------------------------------- /** * Sets the middle name. * @param middleName the new value * @return this, for chaining, not null */ public Builder middleName(String middleName) { this.middleName = middleName; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("SimpleSubPersonWithBuilderNonFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("middleName").append('=').append(JodaBeanUtils.toString(middleName)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SubDecimal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.math.BigDecimal; import java.math.BigInteger; /** * Mock, used for testing. */ public class SubDecimal extends BigDecimal { private static final long serialVersionUID = 1L; public SubDecimal(BigInteger val) { super(val); } } ================================================ FILE: src/test/java/org/joda/beans/sample/SubPerson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock sub person, a generic sub-class of a non-generic superclass. * * @author Stephen Colebourne */ @BeanDefinition(metaScope = "public") public class SubPerson extends DirectBean { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SubPerson}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static SubPerson.Meta meta() { return SubPerson.Meta.INSTANCE; } /** * The meta-bean for {@code SubPerson}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static SubPerson.Meta metaSubPerson(Class cls) { return SubPerson.Meta.INSTANCE; } static { MetaBean.register(SubPerson.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public SubPerson.Meta metaBean() { return SubPerson.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public SubPerson clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return true; } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("SubPerson{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { } //----------------------------------------------------------------------- /** * The meta-bean for {@code SubPerson}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null); /** * Restricted constructor. */ protected Meta() { } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new SubPerson()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) SubPerson.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SubValidateBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock used for subclass validation. * * @author Stephen Colebourne */ @BeanDefinition public class SubValidateBean extends ValidateBean { /** * The sub non-null value. */ @PropertyDefinition(validate = "notNull") private String sub; public SubValidateBean() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SubValidateBean}. * @return the meta-bean, not null */ public static SubValidateBean.Meta meta() { return SubValidateBean.Meta.INSTANCE; } static { MetaBean.register(SubValidateBean.Meta.INSTANCE); } @Override public SubValidateBean.Meta metaBean() { return SubValidateBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the sub non-null value. * @return the value of the property, not null */ public String getSub() { return sub; } /** * Sets the sub non-null value. * @param sub the new value of the property, not null */ public void setSub(String sub) { JodaBeanUtils.notNull(sub, "sub"); this.sub = sub; } /** * Gets the the {@code sub} property. * @return the property, not null */ public final Property sub() { return metaBean().sub().createProperty(this); } //----------------------------------------------------------------------- @Override public SubValidateBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SubValidateBean other = (SubValidateBean) obj; return JodaBeanUtils.equal(this.getSub(), other.getSub()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getSub()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("SubValidateBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("sub").append('=').append(JodaBeanUtils.toString(getSub())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SubValidateBean}. */ public static class Meta extends ValidateBean.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code sub} property. */ private final MetaProperty sub = DirectMetaProperty.ofReadWrite( this, "sub", SubValidateBean.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "sub"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 114240: // sub return this.sub; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new SubValidateBean()); } @Override public Class beanType() { return SubValidateBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code sub} property. * @return the meta-property, not null */ public final MetaProperty sub() { return sub; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 114240: // sub return ((SubValidateBean) bean).getSub(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 114240: // sub ((SubValidateBean) bean).setSub((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((SubValidateBean) bean).sub, "sub"); super.validate(bean); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/SubWrapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class SubWrapper extends Wrapper { /** The name. */ @PropertyDefinition private String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code SubWrapper}. * @return the meta-bean, not null */ public static SubWrapper.Meta meta() { return SubWrapper.Meta.INSTANCE; } static { MetaBean.register(SubWrapper.Meta.INSTANCE); } @Override public SubWrapper.Meta metaBean() { return SubWrapper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property */ public void setName(String name) { this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public final Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- @Override public SubWrapper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { SubWrapper other = (SubWrapper) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("SubWrapper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code SubWrapper}. */ public static class Meta extends Wrapper.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", SubWrapper.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "name"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new SubWrapper()); } @Override public Class beanType() { return SubWrapper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public final MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((SubWrapper) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((SubWrapper) bean).setName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/TestRWOnlyBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import org.junit.jupiter.api.Test; /** * Test RWOnlyBean. */ public class TestRWOnlyBean extends RWOnlyBean { @Test public void test_ro() { assertThat(getRo()).isNull(); assertThat(ro().get()).isNull(); } @Test public void test_wo1() { setWo("woo"); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> property("wo").get()); } @Test public void test_wo2() { setWo("woo"); assertThatExceptionOfType(UnsupportedOperationException.class) .isThrownBy(() -> wo().get()); } @Test public void test_manualGet() { assertThat(getManualGet()).isEqualTo("goo"); assertThat(manualGet().get()).isEqualTo("goo"); } @Test public void test_derived() { assertThat(getDerived()).isEqualTo("drv"); assertThat(derived().get()).isEqualTo("drv"); } } ================================================ FILE: src/test/java/org/joda/beans/sample/TupleFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock tuple, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(builderScope = "package", metaScope = "package") public final class TupleFinal implements Bean { /** * The first value. */ @PropertyDefinition private X first; /** * The second value. */ @PropertyDefinition private Y second; /** * The third value. */ @PropertyDefinition private Z third; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code TupleFinal}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static TupleFinal.Meta meta() { return TupleFinal.Meta.INSTANCE; } /** * The meta-bean for {@code TupleFinal}. * @param the first generic type * @param the second generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @param cls3 the third generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static TupleFinal.Meta metaTupleFinal(Class cls1, Class cls2, Class cls3) { return TupleFinal.Meta.INSTANCE; } static { MetaBean.register(TupleFinal.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @param the type * @param the type * @return the builder, not null */ static TupleFinal.Builder builder() { return new TupleFinal.Builder<>(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ private TupleFinal(TupleFinal.Builder builder) { this.first = builder.first; this.second = builder.second; this.third = builder.third; } @SuppressWarnings("unchecked") @Override public TupleFinal.Meta metaBean() { return TupleFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public X getFirst() { return first; } /** * Sets the first value. * @param first the new value of the property */ public void setFirst(X first) { this.first = first; } /** * Gets the the {@code first} property. * @return the property, not null */ public Property first() { return metaBean().first().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public Y getSecond() { return second; } /** * Sets the second value. * @param second the new value of the property */ public void setSecond(Y second) { this.second = second; } /** * Gets the the {@code second} property. * @return the property, not null */ public Property second() { return metaBean().second().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the third value. * @return the value of the property */ public Z getThird() { return third; } /** * Sets the third value. * @param third the new value of the property */ public void setThird(Z third) { this.third = third; } /** * Gets the the {@code third} property. * @return the property, not null */ public Property third() { return metaBean().third().createProperty(this); } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ Builder toBuilder() { return new Builder<>(this); } @Override public TupleFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { TupleFinal other = (TupleFinal) obj; return JodaBeanUtils.equal(this.getFirst(), other.getFirst()) && JodaBeanUtils.equal(this.getSecond(), other.getSecond()) && JodaBeanUtils.equal(this.getThird(), other.getThird()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getFirst()); hash = hash * 31 + JodaBeanUtils.hashCode(getSecond()); hash = hash * 31 + JodaBeanUtils.hashCode(getThird()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("TupleFinal{"); buf.append("first").append('=').append(JodaBeanUtils.toString(getFirst())).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(getSecond())).append(',').append(' '); buf.append("third").append('=').append(JodaBeanUtils.toString(getThird())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code TupleFinal}. * @param the type * @param the type * @param the type */ static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty first = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "first", TupleFinal.class, Object.class); /** * The meta-property for the {@code second} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty second = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "second", TupleFinal.class, Object.class); /** * The meta-property for the {@code third} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty third = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "third", TupleFinal.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second", "third"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; case 110331239: // third return this.third; } return super.metaPropertyGet(propertyName); } @Override public TupleFinal.Builder builder() { return new TupleFinal.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) TupleFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public MetaProperty second() { return second; } /** * The meta-property for the {@code third} property. * @return the meta-property, not null */ public MetaProperty third() { return third; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((TupleFinal) bean).getFirst(); case -906279820: // second return ((TupleFinal) bean).getSecond(); case 110331239: // third return ((TupleFinal) bean).getThird(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first ((TupleFinal) bean).setFirst((X) newValue); return; case -906279820: // second ((TupleFinal) bean).setSecond((Y) newValue); return; case 110331239: // third ((TupleFinal) bean).setThird((Z) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code TupleFinal}. * @param the type * @param the type * @param the type */ static final class Builder extends DirectFieldsBeanBuilder> { private X first; private Y second; private Z third; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(TupleFinal beanToCopy) { this.first = beanToCopy.getFirst(); this.second = beanToCopy.getSecond(); this.third = beanToCopy.getThird(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; case 110331239: // third return this.third; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 97440432: // first this.first = (X) newValue; break; case -906279820: // second this.second = (Y) newValue; break; case 110331239: // third this.third = (Z) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public TupleFinal build() { return new TupleFinal<>(this); } //----------------------------------------------------------------------- /** * Sets the first value. * @param first the new value * @return this, for chaining, not null */ public Builder first(X first) { this.first = first; return this; } /** * Sets the second value. * @param second the new value * @return this, for chaining, not null */ public Builder second(Y second) { this.second = second; return this; } /** * Sets the third value. * @param third the new value * @return this, for chaining, not null */ public Builder third(Z third) { this.third = third; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("TupleFinal.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)).append(',').append(' '); buf.append("third").append('=').append(JodaBeanUtils.toString(third)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/TupleImmutable.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock tuple, used for testing. * * @author Stephen Colebourne */ @BeanDefinition(metaScope = "package") public final class TupleImmutable implements ImmutableBean { /** * The first value. */ @PropertyDefinition private final X first; /** * The second value. */ @PropertyDefinition private final Y second; /** * The third value. */ @PropertyDefinition private final Z third; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code TupleImmutable}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static TupleImmutable.Meta meta() { return TupleImmutable.Meta.INSTANCE; } /** * The meta-bean for {@code TupleImmutable}. * @param the first generic type * @param the second generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @param cls3 the third generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static TupleImmutable.Meta metaTupleImmutable(Class cls1, Class cls2, Class cls3) { return TupleImmutable.Meta.INSTANCE; } static { MetaBean.register(TupleImmutable.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @param the type * @param the type * @return the builder, not null */ public static TupleImmutable.Builder builder() { return new TupleImmutable.Builder<>(); } private TupleImmutable( X first, Y second, Z third) { this.first = first; this.second = second; this.third = third; } @SuppressWarnings("unchecked") @Override public TupleImmutable.Meta metaBean() { return TupleImmutable.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public X getFirst() { return first; } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public Y getSecond() { return second; } //----------------------------------------------------------------------- /** * Gets the third value. * @return the value of the property */ public Z getThird() { return third; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { TupleImmutable other = (TupleImmutable) obj; return JodaBeanUtils.equal(this.first, other.first) && JodaBeanUtils.equal(this.second, other.second) && JodaBeanUtils.equal(this.third, other.third); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(first); hash = hash * 31 + JodaBeanUtils.hashCode(second); hash = hash * 31 + JodaBeanUtils.hashCode(third); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("TupleImmutable{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)).append(',').append(' '); buf.append("third").append('=').append(JodaBeanUtils.toString(third)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code TupleImmutable}. * @param the type * @param the type * @param the type */ static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty first = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "first", TupleImmutable.class, Object.class); /** * The meta-property for the {@code second} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty second = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "second", TupleImmutable.class, Object.class); /** * The meta-property for the {@code third} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty third = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "third", TupleImmutable.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second", "third"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; case 110331239: // third return this.third; } return super.metaPropertyGet(propertyName); } @Override public TupleImmutable.Builder builder() { return new TupleImmutable.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) TupleImmutable.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public MetaProperty second() { return second; } /** * The meta-property for the {@code third} property. * @return the meta-property, not null */ public MetaProperty third() { return third; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((TupleImmutable) bean).getFirst(); case -906279820: // second return ((TupleImmutable) bean).getSecond(); case 110331239: // third return ((TupleImmutable) bean).getThird(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code TupleImmutable}. * @param the type * @param the type * @param the type */ public static final class Builder extends DirectFieldsBeanBuilder> { private X first; private Y second; private Z third; /** * Restricted constructor. */ private Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(TupleImmutable beanToCopy) { this.first = beanToCopy.getFirst(); this.second = beanToCopy.getSecond(); this.third = beanToCopy.getThird(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; case 110331239: // third return this.third; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 97440432: // first this.first = (X) newValue; break; case -906279820: // second this.second = (Y) newValue; break; case 110331239: // third this.third = (Z) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public TupleImmutable build() { return new TupleImmutable<>( first, second, third); } //----------------------------------------------------------------------- /** * Sets the first value. * @param first the new value * @return this, for chaining, not null */ public Builder first(X first) { this.first = first; return this; } /** * Sets the second value. * @param second the new value * @return this, for chaining, not null */ public Builder second(Y second) { this.second = second; return this; } /** * Sets the third value. * @param third the new value * @return this, for chaining, not null */ public Builder third(Z third) { this.third = third; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("TupleImmutable.Builder{"); buf.append("first").append('=').append(JodaBeanUtils.toString(first)).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(second)).append(',').append(' '); buf.append("third").append('=').append(JodaBeanUtils.toString(third)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/TupleNonFinal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock tuple, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class TupleNonFinal extends DirectBean { /** * The first value. */ @PropertyDefinition private X first; /** * The second value. */ @PropertyDefinition private Y second; /** * The third value. */ @PropertyDefinition private Z third; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code TupleNonFinal}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static TupleNonFinal.Meta meta() { return TupleNonFinal.Meta.INSTANCE; } /** * The meta-bean for {@code TupleNonFinal}. * @param the first generic type * @param the second generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @param cls3 the third generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static TupleNonFinal.Meta metaTupleNonFinal(Class cls1, Class cls2, Class cls3) { return TupleNonFinal.Meta.INSTANCE; } static { MetaBean.register(TupleNonFinal.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public TupleNonFinal.Meta metaBean() { return TupleNonFinal.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the first value. * @return the value of the property */ public X getFirst() { return first; } /** * Sets the first value. * @param first the new value of the property */ public void setFirst(X first) { this.first = first; } /** * Gets the the {@code first} property. * @return the property, not null */ public final Property first() { return metaBean().first().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the second value. * @return the value of the property */ public Y getSecond() { return second; } /** * Sets the second value. * @param second the new value of the property */ public void setSecond(Y second) { this.second = second; } /** * Gets the the {@code second} property. * @return the property, not null */ public final Property second() { return metaBean().second().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the third value. * @return the value of the property */ public Z getThird() { return third; } /** * Sets the third value. * @param third the new value of the property */ public void setThird(Z third) { this.third = third; } /** * Gets the the {@code third} property. * @return the property, not null */ public final Property third() { return metaBean().third().createProperty(this); } //----------------------------------------------------------------------- @Override public TupleNonFinal clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { TupleNonFinal other = (TupleNonFinal) obj; return JodaBeanUtils.equal(this.getFirst(), other.getFirst()) && JodaBeanUtils.equal(this.getSecond(), other.getSecond()) && JodaBeanUtils.equal(this.getThird(), other.getThird()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getFirst()); hash = hash * 31 + JodaBeanUtils.hashCode(getSecond()); hash = hash * 31 + JodaBeanUtils.hashCode(getThird()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("TupleNonFinal{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("first").append('=').append(JodaBeanUtils.toString(getFirst())).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(getSecond())).append(',').append(' '); buf.append("third").append('=').append(JodaBeanUtils.toString(getThird())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code TupleNonFinal}. * @param the type * @param the type * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty first = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "first", TupleNonFinal.class, Object.class); /** * The meta-property for the {@code second} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty second = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "second", TupleNonFinal.class, Object.class); /** * The meta-property for the {@code third} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty third = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "third", TupleNonFinal.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second", "third"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; case 110331239: // third return this.third; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new TupleNonFinal()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) TupleNonFinal.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public final MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public final MetaProperty second() { return second; } /** * The meta-property for the {@code third} property. * @return the meta-property, not null */ public final MetaProperty third() { return third; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((TupleNonFinal) bean).getFirst(); case -906279820: // second return ((TupleNonFinal) bean).getSecond(); case 110331239: // third return ((TupleNonFinal) bean).getThird(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first ((TupleNonFinal) bean).setFirst((X) newValue); return; case -906279820: // second ((TupleNonFinal) bean).setSecond((Y) newValue); return; case 110331239: // third ((TupleNonFinal) bean).setThird((Z) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/TupleSub.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock tuple, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public final class TupleSub extends TupleNonFinal { @PropertyDefinition private String name; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code TupleSub}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static TupleSub.Meta meta() { return TupleSub.Meta.INSTANCE; } /** * The meta-bean for {@code TupleSub}. * @param the first generic type * @param the second generic type * @param the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @param cls3 the third generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static TupleSub.Meta metaTupleSub(Class cls1, Class cls2, Class cls3) { return TupleSub.Meta.INSTANCE; } static { MetaBean.register(TupleSub.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public TupleSub.Meta metaBean() { return TupleSub.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the name. * @return the value of the property */ public String getName() { return name; } /** * Sets the name. * @param name the new value of the property */ public void setName(String name) { this.name = name; } /** * Gets the the {@code name} property. * @return the property, not null */ public Property name() { return metaBean().name().createProperty(this); } //----------------------------------------------------------------------- @Override public TupleSub clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { TupleSub other = (TupleSub) obj; return JodaBeanUtils.equal(this.getName(), other.getName()) && super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; hash = hash * 31 + JodaBeanUtils.hashCode(getName()); return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("TupleSub{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("name").append('=').append(JodaBeanUtils.toString(getName())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code TupleSub}. * @param the type * @param the type * @param the type */ public static final class Meta extends TupleNonFinal.Meta { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code name} property. */ private final MetaProperty name = DirectMetaProperty.ofReadWrite( this, "name", TupleSub.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "name"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3373707: // name return this.name; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder> builder() { return new DirectBeanBuilder<>(new TupleSub()); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) TupleSub.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code name} property. * @return the meta-property, not null */ public MetaProperty name() { return name; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name return ((TupleSub) bean).getName(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3373707: // name ((TupleSub) bean).setName((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/TweakedPair.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock pair, used for testing. * This class adds no extra properties. * * @author Stephen Colebourne */ @BeanDefinition public class TweakedPair extends Pair { //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code TweakedPair}. * @return the meta-bean, not null */ public static TweakedPair.Meta meta() { return TweakedPair.Meta.INSTANCE; } static { MetaBean.register(TweakedPair.Meta.INSTANCE); } @Override public TweakedPair.Meta metaBean() { return TweakedPair.Meta.INSTANCE; } //----------------------------------------------------------------------- @Override public TweakedPair clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { return super.equals(obj); } return false; } @Override public int hashCode() { int hash = 7; return hash ^ super.hashCode(); } @Override public String toString() { StringBuilder buf = new StringBuilder(32); buf.append("TweakedPair{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); } //----------------------------------------------------------------------- /** * The meta-bean for {@code TweakedPair}. */ public static class Meta extends Pair.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap()); /** * Restricted constructor. */ protected Meta() { } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new TweakedPair()); } @Override public Class beanType() { return TweakedPair.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/UserAccount.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Date; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * A user account class, used to demonstrate usage of Joda-Beans. */ @BeanDefinition public final class UserAccount implements Bean { /** * The user identifier. */ @PropertyDefinition(validate = "notEmpty") private String userId; /** * The email address. */ @PropertyDefinition(validate = "notEmpty") private String emailAddress; /** * The number of logins. */ @PropertyDefinition private int numberLogins; /** * The last login instant. */ @PropertyDefinition(validate = "notNull") private Date lastLogin; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code UserAccount}. * @return the meta-bean, not null */ public static UserAccount.Meta meta() { return UserAccount.Meta.INSTANCE; } static { MetaBean.register(UserAccount.Meta.INSTANCE); } @Override public UserAccount.Meta metaBean() { return UserAccount.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the user identifier. * @return the value of the property, not empty */ public String getUserId() { return userId; } /** * Sets the user identifier. * @param userId the new value of the property, not empty */ public void setUserId(String userId) { JodaBeanUtils.notEmpty(userId, "userId"); this.userId = userId; } /** * Gets the the {@code userId} property. * @return the property, not null */ public Property userId() { return metaBean().userId().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the email address. * @return the value of the property, not empty */ public String getEmailAddress() { return emailAddress; } /** * Sets the email address. * @param emailAddress the new value of the property, not empty */ public void setEmailAddress(String emailAddress) { JodaBeanUtils.notEmpty(emailAddress, "emailAddress"); this.emailAddress = emailAddress; } /** * Gets the the {@code emailAddress} property. * @return the property, not null */ public Property emailAddress() { return metaBean().emailAddress().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the number of logins. * @return the value of the property */ public int getNumberLogins() { return numberLogins; } /** * Sets the number of logins. * @param numberLogins the new value of the property */ public void setNumberLogins(int numberLogins) { this.numberLogins = numberLogins; } /** * Gets the the {@code numberLogins} property. * @return the property, not null */ public Property numberLogins() { return metaBean().numberLogins().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the last login instant. * @return the value of the property, not null */ public Date getLastLogin() { return lastLogin; } /** * Sets the last login instant. * @param lastLogin the new value of the property, not null */ public void setLastLogin(Date lastLogin) { JodaBeanUtils.notNull(lastLogin, "lastLogin"); this.lastLogin = lastLogin; } /** * Gets the the {@code lastLogin} property. * @return the property, not null */ public Property lastLogin() { return metaBean().lastLogin().createProperty(this); } //----------------------------------------------------------------------- @Override public UserAccount clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { UserAccount other = (UserAccount) obj; return JodaBeanUtils.equal(this.getUserId(), other.getUserId()) && JodaBeanUtils.equal(this.getEmailAddress(), other.getEmailAddress()) && (this.getNumberLogins() == other.getNumberLogins()) && JodaBeanUtils.equal(this.getLastLogin(), other.getLastLogin()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getUserId()); hash = hash * 31 + JodaBeanUtils.hashCode(getEmailAddress()); hash = hash * 31 + JodaBeanUtils.hashCode(getNumberLogins()); hash = hash * 31 + JodaBeanUtils.hashCode(getLastLogin()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(160); buf.append("UserAccount{"); buf.append("userId").append('=').append(JodaBeanUtils.toString(getUserId())).append(',').append(' '); buf.append("emailAddress").append('=').append(JodaBeanUtils.toString(getEmailAddress())).append(',').append(' '); buf.append("numberLogins").append('=').append(JodaBeanUtils.toString(getNumberLogins())).append(',').append(' '); buf.append("lastLogin").append('=').append(JodaBeanUtils.toString(getLastLogin())); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code UserAccount}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code userId} property. */ private final MetaProperty userId = DirectMetaProperty.ofReadWrite( this, "userId", UserAccount.class, String.class); /** * The meta-property for the {@code emailAddress} property. */ private final MetaProperty emailAddress = DirectMetaProperty.ofReadWrite( this, "emailAddress", UserAccount.class, String.class); /** * The meta-property for the {@code numberLogins} property. */ private final MetaProperty numberLogins = DirectMetaProperty.ofReadWrite( this, "numberLogins", UserAccount.class, Integer.TYPE); /** * The meta-property for the {@code lastLogin} property. */ private final MetaProperty lastLogin = DirectMetaProperty.ofReadWrite( this, "lastLogin", UserAccount.class, Date.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "userId", "emailAddress", "numberLogins", "lastLogin"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case -836030906: // userId return this.userId; case -1070931784: // emailAddress return this.emailAddress; case 850160339: // numberLogins return this.numberLogins; case 1995610739: // lastLogin return this.lastLogin; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new UserAccount()); } @Override public Class beanType() { return UserAccount.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code userId} property. * @return the meta-property, not null */ public MetaProperty userId() { return userId; } /** * The meta-property for the {@code emailAddress} property. * @return the meta-property, not null */ public MetaProperty emailAddress() { return emailAddress; } /** * The meta-property for the {@code numberLogins} property. * @return the meta-property, not null */ public MetaProperty numberLogins() { return numberLogins; } /** * The meta-property for the {@code lastLogin} property. * @return the meta-property, not null */ public MetaProperty lastLogin() { return lastLogin; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case -836030906: // userId return ((UserAccount) bean).getUserId(); case -1070931784: // emailAddress return ((UserAccount) bean).getEmailAddress(); case 850160339: // numberLogins return ((UserAccount) bean).getNumberLogins(); case 1995610739: // lastLogin return ((UserAccount) bean).getLastLogin(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case -836030906: // userId ((UserAccount) bean).setUserId((String) newValue); return; case -1070931784: // emailAddress ((UserAccount) bean).setEmailAddress((String) newValue); return; case 850160339: // numberLogins ((UserAccount) bean).setNumberLogins((Integer) newValue); return; case 1995610739: // lastLogin ((UserAccount) bean).setLastLogin((Date) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notEmpty(((UserAccount) bean).userId, "userId"); JodaBeanUtils.notEmpty(((UserAccount) bean).emailAddress, "emailAddress"); JodaBeanUtils.notNull(((UserAccount) bean).lastLogin, "lastLogin"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ValidateBean.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock used for test equals. * * @author Stephen Colebourne */ @BeanDefinition public class ValidateBean extends DirectBean { /** * The non-null value. */ @PropertyDefinition(validate = "notNull") private String first; /** * The non-empty value. */ @PropertyDefinition(validate = "notEmpty") private String second; /** * The static checked value. */ @PropertyDefinition(validate = "ValidateBeanCheck.checkInTest") private String third; /** * The locally checked value. */ @PropertyDefinition(validate = "checkInBean") private String fourth; /** * The non-blank value. */ @PropertyDefinition(validate = "notBlank") private String fifth; public ValidateBean() { } private static void checkInBean(String value, String propertyName) { if ("D".equals(value) == false) { throw new IllegalArgumentException(propertyName); } } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code ValidateBean}. * @return the meta-bean, not null */ public static ValidateBean.Meta meta() { return ValidateBean.Meta.INSTANCE; } static { MetaBean.register(ValidateBean.Meta.INSTANCE); } @Override public ValidateBean.Meta metaBean() { return ValidateBean.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the non-null value. * @return the value of the property, not null */ public String getFirst() { return first; } /** * Sets the non-null value. * @param first the new value of the property, not null */ public void setFirst(String first) { JodaBeanUtils.notNull(first, "first"); this.first = first; } /** * Gets the the {@code first} property. * @return the property, not null */ public final Property first() { return metaBean().first().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the non-empty value. * @return the value of the property, not empty */ public String getSecond() { return second; } /** * Sets the non-empty value. * @param second the new value of the property, not empty */ public void setSecond(String second) { JodaBeanUtils.notEmpty(second, "second"); this.second = second; } /** * Gets the the {@code second} property. * @return the property, not null */ public final Property second() { return metaBean().second().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the static checked value. * @return the value of the property */ public String getThird() { return third; } /** * Sets the static checked value. * @param third the new value of the property */ public void setThird(String third) { ValidateBeanCheck.checkInTest(third, "third"); this.third = third; } /** * Gets the the {@code third} property. * @return the property, not null */ public final Property third() { return metaBean().third().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the locally checked value. * @return the value of the property */ public String getFourth() { return fourth; } /** * Sets the locally checked value. * @param fourth the new value of the property */ public void setFourth(String fourth) { checkInBean(fourth, "fourth"); this.fourth = fourth; } /** * Gets the the {@code fourth} property. * @return the property, not null */ public final Property fourth() { return metaBean().fourth().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the non-blank value. * @return the value of the property, not blank */ public String getFifth() { return fifth; } /** * Sets the non-blank value. * @param fifth the new value of the property, not blank */ public void setFifth(String fifth) { JodaBeanUtils.notBlank(fifth, "fifth"); this.fifth = fifth; } /** * Gets the the {@code fifth} property. * @return the property, not null */ public final Property fifth() { return metaBean().fifth().createProperty(this); } //----------------------------------------------------------------------- @Override public ValidateBean clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { ValidateBean other = (ValidateBean) obj; return JodaBeanUtils.equal(this.getFirst(), other.getFirst()) && JodaBeanUtils.equal(this.getSecond(), other.getSecond()) && JodaBeanUtils.equal(this.getThird(), other.getThird()) && JodaBeanUtils.equal(this.getFourth(), other.getFourth()) && JodaBeanUtils.equal(this.getFifth(), other.getFifth()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getFirst()); hash = hash * 31 + JodaBeanUtils.hashCode(getSecond()); hash = hash * 31 + JodaBeanUtils.hashCode(getThird()); hash = hash * 31 + JodaBeanUtils.hashCode(getFourth()); hash = hash * 31 + JodaBeanUtils.hashCode(getFifth()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(192); buf.append("ValidateBean{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("first").append('=').append(JodaBeanUtils.toString(getFirst())).append(',').append(' '); buf.append("second").append('=').append(JodaBeanUtils.toString(getSecond())).append(',').append(' '); buf.append("third").append('=').append(JodaBeanUtils.toString(getThird())).append(',').append(' '); buf.append("fourth").append('=').append(JodaBeanUtils.toString(getFourth())).append(',').append(' '); buf.append("fifth").append('=').append(JodaBeanUtils.toString(getFifth())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ValidateBean}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code first} property. */ private final MetaProperty first = DirectMetaProperty.ofReadWrite( this, "first", ValidateBean.class, String.class); /** * The meta-property for the {@code second} property. */ private final MetaProperty second = DirectMetaProperty.ofReadWrite( this, "second", ValidateBean.class, String.class); /** * The meta-property for the {@code third} property. */ private final MetaProperty third = DirectMetaProperty.ofReadWrite( this, "third", ValidateBean.class, String.class); /** * The meta-property for the {@code fourth} property. */ private final MetaProperty fourth = DirectMetaProperty.ofReadWrite( this, "fourth", ValidateBean.class, String.class); /** * The meta-property for the {@code fifth} property. */ private final MetaProperty fifth = DirectMetaProperty.ofReadWrite( this, "fifth", ValidateBean.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "first", "second", "third", "fourth", "fifth"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 97440432: // first return this.first; case -906279820: // second return this.second; case 110331239: // third return this.third; case -1268684262: // fourth return this.fourth; case 97428919: // fifth return this.fifth; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new ValidateBean()); } @Override public Class beanType() { return ValidateBean.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code first} property. * @return the meta-property, not null */ public final MetaProperty first() { return first; } /** * The meta-property for the {@code second} property. * @return the meta-property, not null */ public final MetaProperty second() { return second; } /** * The meta-property for the {@code third} property. * @return the meta-property, not null */ public final MetaProperty third() { return third; } /** * The meta-property for the {@code fourth} property. * @return the meta-property, not null */ public final MetaProperty fourth() { return fourth; } /** * The meta-property for the {@code fifth} property. * @return the meta-property, not null */ public final MetaProperty fifth() { return fifth; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first return ((ValidateBean) bean).getFirst(); case -906279820: // second return ((ValidateBean) bean).getSecond(); case 110331239: // third return ((ValidateBean) bean).getThird(); case -1268684262: // fourth return ((ValidateBean) bean).getFourth(); case 97428919: // fifth return ((ValidateBean) bean).getFifth(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 97440432: // first ((ValidateBean) bean).setFirst((String) newValue); return; case -906279820: // second ((ValidateBean) bean).setSecond((String) newValue); return; case 110331239: // third ((ValidateBean) bean).setThird((String) newValue); return; case -1268684262: // fourth ((ValidateBean) bean).setFourth((String) newValue); return; case 97428919: // fifth ((ValidateBean) bean).setFifth((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((ValidateBean) bean).first, "first"); JodaBeanUtils.notEmpty(((ValidateBean) bean).second, "second"); ValidateBeanCheck.checkInTest(((ValidateBean) bean).third, "third"); checkInBean(((ValidateBean) bean).fourth, "fourth"); JodaBeanUtils.notBlank(((ValidateBean) bean).fifth, "fifth"); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/ValidateBeanCheck.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import org.joda.beans.gen.PropertyDefinition; /** * Class to prove that {@link PropertyDefinition#validate()} works with an external class. */ class ValidateBeanCheck { static void checkInTest(Object value, String name) { if ("C".equals(value)) { return; } throw new IllegalArgumentException(name); } } ================================================ FILE: src/test/java/org/joda/beans/sample/WeirdFormat.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock. * * @author Stephen Colebourne */ @BeanDefinition public class WeirdFormat implements Bean { @PropertyDefinition private String forename1=""; @PropertyDefinition private String forename2 =""; @PropertyDefinition private String forename3= ""; @PropertyDefinition private String forename4 = ""; @PropertyDefinition private String forename5="="; /** * Creates an instance. */ public WeirdFormat() { } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code WeirdFormat}. * @return the meta-bean, not null */ public static WeirdFormat.Meta meta() { return WeirdFormat.Meta.INSTANCE; } static { MetaBean.register(WeirdFormat.Meta.INSTANCE); } @Override public WeirdFormat.Meta metaBean() { return WeirdFormat.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the forename1. * @return the value of the property */ public String getForename1() { return forename1; } /** * Sets the forename1. * @param forename1 the new value of the property */ public void setForename1(String forename1) { this.forename1 = forename1; } /** * Gets the the {@code forename1} property. * @return the property, not null */ public final Property forename1() { return metaBean().forename1().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the forename2. * @return the value of the property */ public String getForename2() { return forename2; } /** * Sets the forename2. * @param forename2 the new value of the property */ public void setForename2(String forename2) { this.forename2 = forename2; } /** * Gets the the {@code forename2} property. * @return the property, not null */ public final Property forename2() { return metaBean().forename2().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the forename3. * @return the value of the property */ public String getForename3() { return forename3; } /** * Sets the forename3. * @param forename3 the new value of the property */ public void setForename3(String forename3) { this.forename3 = forename3; } /** * Gets the the {@code forename3} property. * @return the property, not null */ public final Property forename3() { return metaBean().forename3().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the forename4. * @return the value of the property */ public String getForename4() { return forename4; } /** * Sets the forename4. * @param forename4 the new value of the property */ public void setForename4(String forename4) { this.forename4 = forename4; } /** * Gets the the {@code forename4} property. * @return the property, not null */ public final Property forename4() { return metaBean().forename4().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the forename5. * @return the value of the property */ public String getForename5() { return forename5; } /** * Sets the forename5. * @param forename5 the new value of the property */ public void setForename5(String forename5) { this.forename5 = forename5; } /** * Gets the the {@code forename5} property. * @return the property, not null */ public final Property forename5() { return metaBean().forename5().createProperty(this); } //----------------------------------------------------------------------- @Override public WeirdFormat clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { WeirdFormat other = (WeirdFormat) obj; return JodaBeanUtils.equal(this.getForename1(), other.getForename1()) && JodaBeanUtils.equal(this.getForename2(), other.getForename2()) && JodaBeanUtils.equal(this.getForename3(), other.getForename3()) && JodaBeanUtils.equal(this.getForename4(), other.getForename4()) && JodaBeanUtils.equal(this.getForename5(), other.getForename5()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getForename1()); hash = hash * 31 + JodaBeanUtils.hashCode(getForename2()); hash = hash * 31 + JodaBeanUtils.hashCode(getForename3()); hash = hash * 31 + JodaBeanUtils.hashCode(getForename4()); hash = hash * 31 + JodaBeanUtils.hashCode(getForename5()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(192); buf.append("WeirdFormat{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("forename1").append('=').append(JodaBeanUtils.toString(getForename1())).append(',').append(' '); buf.append("forename2").append('=').append(JodaBeanUtils.toString(getForename2())).append(',').append(' '); buf.append("forename3").append('=').append(JodaBeanUtils.toString(getForename3())).append(',').append(' '); buf.append("forename4").append('=').append(JodaBeanUtils.toString(getForename4())).append(',').append(' '); buf.append("forename5").append('=').append(JodaBeanUtils.toString(getForename5())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code WeirdFormat}. */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code forename1} property. */ private final MetaProperty forename1 = DirectMetaProperty.ofReadWrite( this, "forename1", WeirdFormat.class, String.class); /** * The meta-property for the {@code forename2} property. */ private final MetaProperty forename2 = DirectMetaProperty.ofReadWrite( this, "forename2", WeirdFormat.class, String.class); /** * The meta-property for the {@code forename3} property. */ private final MetaProperty forename3 = DirectMetaProperty.ofReadWrite( this, "forename3", WeirdFormat.class, String.class); /** * The meta-property for the {@code forename4} property. */ private final MetaProperty forename4 = DirectMetaProperty.ofReadWrite( this, "forename4", WeirdFormat.class, String.class); /** * The meta-property for the {@code forename5} property. */ private final MetaProperty forename5 = DirectMetaProperty.ofReadWrite( this, "forename5", WeirdFormat.class, String.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "forename1", "forename2", "forename3", "forename4", "forename5"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1593991114: // forename1 return this.forename1; case 1593991115: // forename2 return this.forename2; case 1593991116: // forename3 return this.forename3; case 1593991117: // forename4 return this.forename4; case 1593991118: // forename5 return this.forename5; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new DirectBeanBuilder<>(new WeirdFormat()); } @Override public Class beanType() { return WeirdFormat.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code forename1} property. * @return the meta-property, not null */ public final MetaProperty forename1() { return forename1; } /** * The meta-property for the {@code forename2} property. * @return the meta-property, not null */ public final MetaProperty forename2() { return forename2; } /** * The meta-property for the {@code forename3} property. * @return the meta-property, not null */ public final MetaProperty forename3() { return forename3; } /** * The meta-property for the {@code forename4} property. * @return the meta-property, not null */ public final MetaProperty forename4() { return forename4; } /** * The meta-property for the {@code forename5} property. * @return the meta-property, not null */ public final MetaProperty forename5() { return forename5; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1593991114: // forename1 return ((WeirdFormat) bean).getForename1(); case 1593991115: // forename2 return ((WeirdFormat) bean).getForename2(); case 1593991116: // forename3 return ((WeirdFormat) bean).getForename3(); case 1593991117: // forename4 return ((WeirdFormat) bean).getForename4(); case 1593991118: // forename5 return ((WeirdFormat) bean).getForename5(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 1593991114: // forename1 ((WeirdFormat) bean).setForename1((String) newValue); return; case 1593991115: // forename2 ((WeirdFormat) bean).setForename2((String) newValue); return; case 1593991116: // forename3 ((WeirdFormat) bean).setForename3((String) newValue); return; case 1593991117: // forename4 ((WeirdFormat) bean).setForename4((String) newValue); return; case 1593991118: // forename5 ((WeirdFormat) bean).setForename5((String) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/Wrapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectBean; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public abstract class Wrapper extends DirectBean { /** The type. */ @PropertyDefinition private String type; /** The surname. */ @PropertyDefinition private T content; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code Wrapper}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static Wrapper.Meta meta() { return Wrapper.Meta.INSTANCE; } /** * The meta-bean for {@code Wrapper}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static Wrapper.Meta metaWrapper(Class cls) { return Wrapper.Meta.INSTANCE; } static { MetaBean.register(Wrapper.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public Wrapper.Meta metaBean() { return Wrapper.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the type. * @return the value of the property */ public String getType() { return type; } /** * Sets the type. * @param type the new value of the property */ public void setType(String type) { this.type = type; } /** * Gets the the {@code type} property. * @return the property, not null */ public final Property type() { return metaBean().type().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the surname. * @return the value of the property */ public T getContent() { return content; } /** * Sets the surname. * @param content the new value of the property */ public void setContent(T content) { this.content = content; } /** * Gets the the {@code content} property. * @return the property, not null */ public final Property content() { return metaBean().content().createProperty(this); } //----------------------------------------------------------------------- @Override public Wrapper clone() { return JodaBeanUtils.cloneAlways(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Wrapper other = (Wrapper) obj; return JodaBeanUtils.equal(this.getType(), other.getType()) && JodaBeanUtils.equal(this.getContent(), other.getContent()); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(getType()); hash = hash * 31 + JodaBeanUtils.hashCode(getContent()); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("Wrapper{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("type").append('=').append(JodaBeanUtils.toString(getType())).append(',').append(' '); buf.append("content").append('=').append(JodaBeanUtils.toString(getContent())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Wrapper}. * @param the type */ public static class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code type} property. */ private final MetaProperty type = DirectMetaProperty.ofReadWrite( this, "type", Wrapper.class, String.class); /** * The meta-property for the {@code content} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty content = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "content", Wrapper.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "type", "content"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3575610: // type return this.type; case 951530617: // content return this.content; } return super.metaPropertyGet(propertyName); } @Override public boolean isBuildable() { return false; } @Override public BeanBuilder> builder() { throw new UnsupportedOperationException("Wrapper is an abstract class"); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) Wrapper.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code type} property. * @return the meta-property, not null */ public final MetaProperty type() { return type; } /** * The meta-property for the {@code content} property. * @return the meta-property, not null */ public final MetaProperty content() { return content; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3575610: // type return ((Wrapper) bean).getType(); case 951530617: // content return ((Wrapper) bean).getContent(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 3575610: // type ((Wrapper) bean).setType((String) newValue); return; case 951530617: // content ((Wrapper) bean).setContent((T) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/sample/WrapperToDoubleGenerics.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.sample; import java.util.Map; import java.util.NoSuchElementException; import org.joda.beans.Bean; import org.joda.beans.ImmutableBean; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.gen.BeanDefinition; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; /** * Mock JavaBean, used for testing. * * @author Stephen Colebourne */ @BeanDefinition public class WrapperToDoubleGenerics> implements ImmutableBean { /** * The type T value. **/ @PropertyDefinition private final T base; //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code WrapperToDoubleGenerics}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static WrapperToDoubleGenerics.Meta meta() { return WrapperToDoubleGenerics.Meta.INSTANCE; } /** * The meta-bean for {@code WrapperToDoubleGenerics}. * @param the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static > WrapperToDoubleGenerics.Meta metaWrapperToDoubleGenerics(Class cls) { return WrapperToDoubleGenerics.Meta.INSTANCE; } static { MetaBean.register(WrapperToDoubleGenerics.Meta.INSTANCE); } /** * Returns a builder used to create an instance of the bean. * @param the type * @return the builder, not null */ public static > WrapperToDoubleGenerics.Builder builder() { return new WrapperToDoubleGenerics.Builder<>(); } /** * Restricted constructor. * @param builder the builder to copy from, not null */ protected WrapperToDoubleGenerics(WrapperToDoubleGenerics.Builder builder) { this.base = builder.base; } @SuppressWarnings("unchecked") @Override public WrapperToDoubleGenerics.Meta metaBean() { return WrapperToDoubleGenerics.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the base. * @return the value of the property */ public T getBase() { return base; } //----------------------------------------------------------------------- /** * Returns a builder that allows this bean to be mutated. * @return the mutable builder, not null */ public Builder toBuilder() { return new Builder<>(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { WrapperToDoubleGenerics other = (WrapperToDoubleGenerics) obj; return JodaBeanUtils.equal(this.base, other.base); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(base); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("WrapperToDoubleGenerics{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("base").append('=').append(JodaBeanUtils.toString(base)).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code WrapperToDoubleGenerics}. * @param the type */ public static class Meta> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code base} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty base = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "base", WrapperToDoubleGenerics.class, Object.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "base"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3016401: // base return this.base; } return super.metaPropertyGet(propertyName); } @Override public WrapperToDoubleGenerics.Builder builder() { return new WrapperToDoubleGenerics.Builder<>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class> beanType() { return (Class) WrapperToDoubleGenerics.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code base} property. * @return the meta-property, not null */ public final MetaProperty base() { return base; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3016401: // base return ((WrapperToDoubleGenerics) bean).getBase(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code WrapperToDoubleGenerics}. * @param the type */ public static class Builder> extends DirectFieldsBeanBuilder> { private T base; /** * Restricted constructor. */ protected Builder() { } /** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ protected Builder(WrapperToDoubleGenerics beanToCopy) { this.base = beanToCopy.getBase(); } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3016401: // base return this.base; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3016401: // base this.base = (T) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder set(MetaProperty property, Object value) { super.set(property, value); return this; } @Override public WrapperToDoubleGenerics build() { return new WrapperToDoubleGenerics<>(this); } //----------------------------------------------------------------------- /** * Sets the base. * @param base the new value * @return this, for chaining, not null */ public Builder base(T base) { this.base = base; return this; } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(64); buf.append("WrapperToDoubleGenerics.Builder{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } protected void toString(StringBuilder buf) { buf.append("base").append('=').append(JodaBeanUtils.toString(base)).append(',').append(' '); } } //-------------------------- AUTOGENERATED END -------------------------- } ================================================ FILE: src/test/java/org/joda/beans/ser/AtomicReference.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Mock class with a silly name. */ class AtomicReference { } ================================================ FILE: src/test/java/org/joda/beans/ser/BigDecimal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Mock class with a silly name. */ class BigDecimal { } ================================================ FILE: src/test/java/org/joda/beans/ser/Normal.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Mock class with a silly name. */ class Normal { } ================================================ FILE: src/test/java/org/joda/beans/ser/SerTestHelper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import java.util.ArrayList; import java.util.Arrays; import java.util.Currency; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.TreeSet; import org.joda.beans.sample.Address; import org.joda.beans.sample.Company; import org.joda.beans.sample.CompanyAddress; import org.joda.beans.sample.INamedKey; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmGeneric; import org.joda.beans.sample.ImmGenericArray; import org.joda.beans.sample.ImmGenericCollections; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmJodaConvertBean; import org.joda.beans.sample.ImmJodaConvertWrapper; import org.joda.beans.sample.ImmKey; import org.joda.beans.sample.ImmKeyHolder; import org.joda.beans.sample.ImmKeyList; import org.joda.beans.sample.ImmNamedKey; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.ImmPair; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.ImmTreeNode; import org.joda.beans.sample.JodaConvertInterface; import org.joda.beans.sample.Person; import org.joda.beans.sample.PrimitiveBean; import org.joda.beans.sample.RiskLevel; import org.joda.beans.sample.RiskPerception; import org.joda.beans.sample.SimpleJson; import org.joda.collect.grid.DenseGrid; import org.joda.collect.grid.SparseGrid; import com.google.common.base.Optional; import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableTable; /** * Test helper. */ public class SerTestHelper { public static ImmGeneric> testBigIntegerList() { var intList = new ArrayList(200000); for (int i = 0; i < 200000; i++) { intList.add(i * 2); } return ImmGeneric.of(intList); } public static ImmGenericArray testBigAddressArray() { var quarterSize = 250; var addressArray = new ImmAddress[quarterSize * 4]; for (int i = 0; i < quarterSize; i++) { addressArray[i] = testImmAddress(true, "Etienne #" + i, i); } System.arraycopy(addressArray, 0, addressArray, quarterSize, quarterSize); System.arraycopy(addressArray, 0, addressArray, quarterSize * 2, quarterSize); System.arraycopy(addressArray, 0, addressArray, quarterSize * 3, quarterSize); return ImmGenericArray.of(addressArray); } public static Address testAddress() { return testAddress("Etienne", 251); } private static Address testAddress(String name, int number) { Person person = new Person(); person.setForename(name); person.setSurname("Colebourne"); person.getExtensions().set("interests", "joda"); person.getExtensions().set("conferenceCount", 21); person.getExtensions().set("quality", 'B'); person.getExtensions().set("company", new Company("OpenGamma")); Address address = new Address(); address.setOwner(person); address.setNumber(number); address.setStreet("Big Road"); address.setCity("London & Capital of the World "); CompanyAddress workAddress = new CompanyAddress(); workAddress.setCompanyName("OpenGamma"); workAddress.setNumber(185); workAddress.setStreet("Park Street"); workAddress.setCity("London"); Address homeAddress = new Address(); homeAddress.setNumber(65432); homeAddress.setStreet("Big Road"); homeAddress.setCity("Bigton"); person.setMainAddress(workAddress); person.getOtherAddressMap().put("home", homeAddress); person.getOtherAddressMap().put("work", workAddress); person.getOtherAddressMap().put("other", null); person.getAddressList().add(homeAddress); person.getAddressList().add(null); person.getAddressList().add(workAddress); person.getAddressesList().add(ImmutableList.of(homeAddress, workAddress)); return address; } public static ImmAddress testImmAddress(boolean isImmutable) { return testImmAddress(isImmutable, "Etienne", 185); } private static ImmAddress testImmAddress(boolean isImmutable, String name, int number) { Map> map = new HashMap<>(); map.put("A", Arrays.asList("B", "b")); Map> map2 = new HashMap<>(); map2.put("A", Arrays.asList(3, 2, 1)); Map>> map3 = new HashMap<>(); map3.put("A", Arrays.asList(Arrays.asList(3, 2, 1))); Map> map4 = new HashMap<>(); Map>> map5 = new HashMap<>(); PrimitiveBean primitives = new PrimitiveBean(); primitives.setValueLong(1L); primitives.setValueInt(2); primitives.setValueShort((short) 3); primitives.setValueByte((byte) 4); primitives.setValueDouble(5.0d); primitives.setValueFloat(6.0f); primitives.setValueChar('7'); primitives.setValueBoolean(true); List objects1 = Arrays.asList(Currency.getInstance("GBP"), TimeZone.getTimeZone("Europe/London")); List objects2 = isImmutable ? Arrays.asList(Locale.CANADA_FRENCH, Long.valueOf(2)) : Arrays.asList(Locale.CANADA_FRENCH, Long.valueOf(2), primitives); map5.put("A", Arrays.asList(objects1)); map5.put("B", Arrays.asList(objects2)); Map map6 = new HashMap<>(); map6.put("A", "Abba"); map6.put("B", ImmutableSet.of("a", "b")); map6.put("C", ImmutableSet.copyOf(objects2)); map6.put("D", ImmutableMap.of("d", 1, "e", 2)); ImmPerson person = ImmPerson.builder() .forename(name) .middleNames("K", "T") .surname("Colebourne") .addressList(isImmutable ? null : Arrays.asList(new Address())) .codeCounts(ImmutableMultiset.of("A", "A", "B")) .build(); ImmPerson child = ImmPerson.builder() .forename("Etiennette") .surname("Colebourne") .build(); ImmPerson child2 = ImmPerson.builder() .forename("Kylie") .surname("Colebourne") .build(); ImmAddress childAddress = ImmAddress.builder() .owner(child) .number(185) .street("Park Street") .city("London") .risk(RiskLevel.LOW) .riskLevel(RiskLevel.HIGH) .riskLevels(EnumSet.of(RiskLevel.LOW, RiskLevel.MEDIUM)) .object1(RiskLevel.MEDIUM) .object2(RiskPerception.LOW) .data(new byte[] {64, 65, 66}) .build(); map4.put(child, ImmutableMap.of("sibling", child2)); HashBasedTable table = HashBasedTable.create(); table.put(1, 1, person); table.put(1, 2, child); table.put(2, 1, child2); SparseGrid sparseGrid = SparseGrid.create(5, 5); sparseGrid.put(1, 1, child2); DenseGrid denseGrid = DenseGrid.create(2, 3); denseGrid.put(0, 0, child); denseGrid.put(1, 1, child2); ImmAddress address = ImmAddress.builder() .owner(person) .number(number) .street("Park Street") .city("London & Capital of the World \n") .abstractNumber(Short.valueOf((short) 89)) .array2d(new String[][] {{"a"}, {}, {"b", "c"}}) .object1(ImmutableList.of("a", "b", "c")) .object2(ImmutableMap.of("d", 1, Currency.getInstance("GBP"), 2)) .serializable(ImmutableList.of("a", "b", "c")) .objectInMap(map6) .listInMap(map) .listNumericInMap(map2) .listInListInMap(map3) .objectListInListInMap(map5) .mapInMap(map4) .simpleTable(ImmutableTable.builder() .put(1, 1, "Hello") .put(1, 2, "There") .build()) .compoundTable(table) .sparseGrid(sparseGrid) .denseGrid(denseGrid) .beanBeanMap(ImmutableMap.of(child, childAddress)) .doubleVector(new double[] {1.1, 2.2, 3.3}) .matrix(new double[][] {{1.1, 2.2}, {3.2}}) .build(); return address; } public static ImmOptional testImmOptional() { ImmOptional optional = ImmOptional.builder() .optString(Optional.of("A")) .build(); return optional; } public static ImmGuava testCollections(boolean extended) { ImmutableList list = ImmutableList.of("A", "B"); ImmutableSet set = ImmutableSet.of("A", "B"); ImmutableSortedSet sortedSet = ImmutableSortedSet.of("A", "B"); ImmutableMap map = ImmutableMap.of("A", "AA", "B", "BB"); ImmutableSortedMap sortedMap = ImmutableSortedMap.of("A", "AA", "B", "BB"); ImmutableBiMap bimap = ImmutableBiMap.of("A", "AA", "B", "BB"); ImmutableMultiset multiset = ImmutableMultiset.of("A", "B", "C", "B", "C", "C"); ImmutableListMultimap listMultimap = ImmutableListMultimap.of("A", "B", "A", "C", "B", "D"); ImmutableSetMultimap setMultimap = ImmutableSetMultimap.of("A", "B", "A", "C", "B", "D"); ImmutableTable table = ImmutableTable.builder() .put("A", 1, "B") .put("A", 2, "C") .put("B", 3, "D") .build(); var builder = ImmGuava.builder() .list(list) .listInterface(list) .set(set) .setInterface(set) .sortedSet(sortedSet) .sortedSetInterface(sortedSet) .map(map) .mapInterface(map) .sortedMap(sortedMap) .sortedMapInterface(sortedMap) .biMap(bimap) .biMapInterface(bimap) .multiset(multiset); if (extended) { // ImmutableMultimap.copyOf always creates a ListMultimap, even though deserialization sends a SetMultimap // so must be .multimapInterface(listMultimap) not .multimapInterface(setMultimap) builder.multimap(listMultimap) .multimapInterface(listMultimap) .listMultimap(listMultimap) .listMultimapInterface(listMultimap) .setMultimap(setMultimap) .setMultimapInterface(setMultimap) .table(table); } return builder.build(); } public static ImmGenericCollections testGenericInterfaces() { return ImmGenericCollections.builder() .map(ImmutableMap.of( "First", JodaConvertInterface.of("First"), "Second", JodaConvertInterface.of("Second"))) .build(); } public static ImmGenericCollections testGenericInterfacesCollections() { return ImmGenericCollections.builder() .map(ImmutableMap.of( "First", Arrays.asList("A", "B"), "First1", ImmutableList.of("A", "B"), "Third1", new TreeSet<>(ImmutableList.of("A", "B")), "Third", new HashSet<>(Arrays.asList("A", "B")), "Second", testCollections(true))) .build(); } public static ImmKeyList testIntermediateInterfaces() { // second serialized as JodaConvertInterface, non-bean // third and fourth are serialized as an intermediate Joda-Convert interface INamedKey // (Root interface) IKey -> (Joda-Convert interface) INamedKey -> (Concrete Bean) ImmNamedKey return ImmKeyList.builder() .keys( ImmKey.builder().name("First").build(), JodaConvertInterface.of("Second"), INamedKey.of("Third"), ImmNamedKey.of("Fourth")) .build(); } public static ImmGenericCollections> testGenericNestedCollections() { return ImmGenericCollections.>builder() .map(ImmutableMap.of( "Key", ImmutableMap.of( new ImmJodaConvertBean("Hello:8"), "Done", new ImmJodaConvertBean("Hello:10"), "Done2"))) .build(); } public static ImmGenericArray> testGenericArrayWithNulls() { return ImmGenericArray.of(new ImmGeneric[] { ImmGeneric.builder() .value("Help") .build(), ImmGeneric.builder() .value(ImmJodaConvertWrapper.of(null, "null")) .build(), ImmGeneric.builder() .value(ImmJodaConvertWrapper.of(new ImmJodaConvertBean("Bean:5"), "null")) .build() }); } public static ImmTreeNode testTree() { ImmutableList childList = ImmutableList.of( ImmTreeNode.builder().name("First child").build(), ImmTreeNode.builder().name("Second child").build(), ImmTreeNode.builder().name("Third child").build()); return ImmTreeNode.of( "Root Node", ImmTreeNode.builder().name("First child").build(), ImmTreeNode.builder().name("Second child").build(), ImmTreeNode.builder().name("Third child").build(), ImmutableList.of( ImmTreeNode.builder().name("First child").build(), ImmTreeNode.builder().name("Third child").build(), ImmTreeNode.builder() .name("Fourth child") .child3(ImmTreeNode.builder().name("Third child") .childList(childList) .build()) .childList(childList) .build())); } public static ImmKeyHolder testImmKeyHolder() { return ImmKeyHolder.builder() .value(ImmKey.builder().name("foo").build()) .build(); } public static SimpleJson testSimpleJson() { Map> map = new HashMap<>(); map.put("A", Arrays.asList("B", "b")); Map> map2 = new HashMap<>(); map2.put("A", Arrays.asList(3, 2, 1)); ImmKey key1 = ImmKey.builder().name("Cat").build(); ImmKey key2 = ImmKey.builder().name("Dog").build(); SimpleJson result = SimpleJson.builder() .primitiveChar('a') .primitiveByte((byte) 23) .primitiveShort((short) 12) .primitiveInt(9) .primitiveLong(6) .primitiveFloat(3.4f) .primitiveDouble(2.3d) .primitiveDoubleNaN(Double.NaN) .primitiveDoubleInf(Double.POSITIVE_INFINITY) .abstractNumber(Integer.valueOf(29)) .arrayByte(new byte[] {64, 65, 66}) .array2d(new String[][] {{"a"}, {}, {"b", "c"}}) .string("ABBA") .bean(key1) .object1(ImmutableList.of("a", "b", "c")) .object2(ImmutableMap.of("d", 1, "12", "2")) .risk(RiskLevel.LOW) .riskLevel(RiskLevel.HIGH) .riskLevels(EnumSet.of(RiskLevel.LOW, RiskLevel.MEDIUM)) .stringList(ImmutableList.of("a", "b", "c")) .beanList(ImmutableList.of(key1, key2)) .stringMap(ImmutableMap.of("a", "A", "b", "B")) .intKeyMap(ImmutableMap.of(1, "A", 2, "B")) .beanMap(ImmutableMap.of("a", key1, "b", key2)) .listInMap(map) .listNumericInMap(map2) .objectInMap(ImmutableMap.of("a", (long) Integer.MAX_VALUE + 1)) .build(); return result; } } ================================================ FILE: src/test/java/org/joda/beans/ser/TestJodaBeanBinFormat.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.ser.bin.JodaBeanBinFormat; import org.junit.jupiter.api.Test; /** * Test {@link JodaBeanBinFormat}. */ class TestJodaBeanBinFormat { @Test void test() { assertThat(JodaBeanBinFormat.STANDARD.version()).isEqualTo(1); assertThat(JodaBeanBinFormat.REFERENCING.version()).isEqualTo(2); } } ================================================ FILE: src/test/java/org/joda/beans/ser/TestLinkedByteArrayOutputStream.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; import org.junit.jupiter.api.Test; /** * Test {@link LinkedByteArrayOutputStream}. */ class TestLinkedByteArrayOutputStream { @Test void test_empty() { try (var test = new LinkedByteArrayOutputStream()) { assertThat(test).hasToString(""); assertThat(test.toByteArray()).isEqualTo(new byte[0]); assertThat(test.size()).isEqualTo(0); } } @Test void test_writeByte() { try (var test = new LinkedByteArrayOutputStream()) { test.write(33); assertThat(test).hasToString("21"); assertThat(test.toByteArray()).isEqualTo(new byte[] {33}); assertThat(test.size()).isEqualTo(1); } } @Test void test_writeByte_growCapacity() { try (var test = new LinkedByteArrayOutputStream()) { test.write(new byte[1024]); test.write(33); assertThat(test.toString()).hasSize(2050).endsWith("0021"); assertThat(test.toByteArray()).hasSize(1025).endsWith(new byte[] {33}); } } @Test void test_writeByteArray_empty() { try (var test = new LinkedByteArrayOutputStream()) { test.write(new byte[0]); assertThat(test).hasToString(""); assertThat(test.toByteArray()).isEqualTo(new byte[0]); assertThat(test.size()).isEqualTo(0); } } @Test void test_writeByteArray_normal() { try (var test = new LinkedByteArrayOutputStream()) { var bytes = new byte[] {33, 34, 35, 36, 37}; test.write(bytes, 1, 3); assertThat(test).hasToString("222324"); assertThat(test.toByteArray()).isEqualTo(new byte[] {34, 35, 36}); assertThat(test.size()).isEqualTo(3); } } @Test void test_writeByteArray_growCapacityExact() { try (var test = new LinkedByteArrayOutputStream()) { var bytes = new byte[] {33, 34, 35, 36, 37}; test.write(new byte[1024]); test.write(bytes, 1, 4); assertThat(test.toString()).hasSize(2056).endsWith("22232425"); assertThat(test.toByteArray()).hasSize(1028).endsWith(new byte[] {34, 35, 36, 37}); assertThat(test.size()).isEqualTo(1028); assertThat(test.toByteArray()).isEqualTo(test.toByteArray()); } } @Test void test_writeByteArray_growCapacitySplit() { try (var test = new LinkedByteArrayOutputStream()) { var bytes = new byte[] {33, 34, 35, 36, 37}; test.write(new byte[1022]); test.write(bytes, 0, 3); assertThat(test.toString()).hasSize(2050).endsWith("212223"); assertThat(test.toByteArray()).hasSize(1025).endsWith(new byte[] {33, 34, 35}); assertThat(test.size()).isEqualTo(1025); assertThat(test.toByteArray()).isEqualTo(test.toByteArray()); } } @Test void test_writeByteArray_large() { try (var test = new LinkedByteArrayOutputStream()) { var bytes = new byte[2048]; Arrays.fill(bytes, (byte) 33); test.write(new byte[1022]); test.write(bytes); test.write(34); assertThat(test.toString()).hasSize((1022 + 2048 + 1) * 2).endsWith("212122"); assertThat(test.toByteArray()).hasSize(1022 + 2048 + 1).endsWith(new byte[] {33, 33, 34}); assertThat(test.size()).isEqualTo(1022 + 2048 + 1); assertThat(test.toByteArray()).isEqualTo(test.toByteArray()); } } } ================================================ FILE: src/test/java/org/joda/beans/ser/TestSerDeserializerProvider.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import static org.assertj.core.api.Assertions.assertThat; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.sample.ImmKey; import org.joda.beans.sample.Pair; import org.joda.beans.sample.Person; import org.junit.jupiter.api.Test; /** * Test {@link SerDeserializerProvider}. */ class TestSerDeserializerProvider { private static final SerDeserializer DESER = new SerDeserializer() { @Override public void setValue(BeanBuilder builder, MetaProperty metaProp, Object value) { } @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { return null; } @Override public MetaBean findMetaBean(Class beanType) { return null; } @Override public BeanBuilder createBuilder(Class beanType, MetaBean metaBean) { return null; } @Override public Object build(Class beanType, BeanBuilder builder) { return null; } }; private static final SerDeserializerProvider PROVIDER = new SerDeserializerProvider() { @Override public SerDeserializer findDeserializer(Class beanType) { return DESER; } }; @Test void test_provider() { SerDeserializers deser = new SerDeserializers(PROVIDER); assertThat(deser.findDeserializer(Person.class)).isSameAs(DESER); } @Test void test_classpathImmKey() { assertThat(SerDeserializers.INSTANCE.getDeserializers()).containsKey(ImmKey.class); assertThat(SerDeserializers.LENIENT.getDeserializers()).containsKey(ImmKey.class); assertThat(new SerDeserializers(PROVIDER).getDeserializers()).containsKey(ImmKey.class); assertThat(SerDeserializers.INSTANCE.findDeserializer(ImmKey.class).findMetaProperty(ImmKey.class, ImmKey.meta(), "key")) .isEqualTo(ImmKey.meta().name()); assertThat(SerDeserializers.LENIENT.findDeserializer(ImmKey.class).findMetaProperty(ImmKey.class, ImmKey.meta(), "wibble")) .isNull(); } @Test void test_classpathPair() { assertThat(SerDeserializers.INSTANCE.getDeserializers()).containsKey(Pair.class); assertThat(SerDeserializers.LENIENT.getDeserializers()).containsKey(Pair.class); assertThat(new SerDeserializers(PROVIDER).getDeserializers()).containsKey(Pair.class); assertThat(SerDeserializers.INSTANCE.findDeserializer(Pair.class).findMetaProperty(Pair.class, Pair.meta(), "left")) .isEqualTo(Pair.meta().first()); assertThat(SerDeserializers.LENIENT.findDeserializer(Pair.class).findMetaProperty(Pair.class, ImmKey.meta(), "wibble")) .isNull(); } } ================================================ FILE: src/test/java/org/joda/beans/ser/TestSerTypeMapper.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.io.File; import java.util.BitSet; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; /** * Test {@link SerTypeMapper}. */ class TestSerTypeMapper { private static final JodaBeanSer SETTINGS = JodaBeanSer.PRETTY; private static final JodaBeanSer SETTINGS_NO_SHORT = JodaBeanSer.PRETTY.withShortTypes(false); @Test void test_encodeType() { Map, String> cache = new HashMap<>(); // base package type assertThat(SerTypeMapper.encodeType(BitSet.class, SETTINGS, "java.util.", cache)).isEqualTo("BitSet"); assertThat(cache.get(BitSet.class)).isEqualTo("BitSet"); // basic type assertThat(SerTypeMapper.encodeType(File.class, SETTINGS, "java.util.", cache)).isEqualTo("File"); assertThat(cache).doesNotContainKey(File.class); // user type assertThat(SerTypeMapper.encodeType(AtomicReference.class, SETTINGS, "java.util.", cache)) .isEqualTo("java.util.concurrent.atomic.AtomicReference"); assertThat(cache.get(AtomicReference.class)).isEqualTo("AtomicReference"); // user type - second occurrence assertThat(SerTypeMapper.encodeType(AtomicReference.class, SETTINGS, "java.util.", cache)).isEqualTo("AtomicReference"); assertThat(cache.get(AtomicReference.class)).isEqualTo("AtomicReference"); // user type - already cached name assertThat(SerTypeMapper.encodeType(org.joda.beans.ser.AtomicReference.class, SETTINGS, "java.util.", cache)) .isEqualTo("org.joda.beans.ser.AtomicReference"); assertThat(cache.get(org.joda.beans.ser.AtomicReference.class)).isEqualTo("org.joda.beans.ser.AtomicReference"); // user type assertThat(SerTypeMapper.encodeType(AtomicIntegerArray.class, SETTINGS, "java.util.", cache)) .isEqualTo("java.util.concurrent.atomic.AtomicIntegerArray"); assertThat(cache.get(AtomicIntegerArray.class)).isEqualTo("AtomicIntegerArray"); // user type - second occurrence assertThat(SerTypeMapper.encodeType(AtomicIntegerArray.class, SETTINGS, "java.util.", cache)).isEqualTo("AtomicIntegerArray"); assertThat(cache.get(AtomicIntegerArray.class)).isEqualTo("AtomicIntegerArray"); // user type - silly name assertThat(SerTypeMapper.encodeType(BigDecimal.class, SETTINGS, "java.util.", cache)).isEqualTo("org.joda.beans.ser.BigDecimal"); assertThat(cache.get(BigDecimal.class)).isEqualTo("org.joda.beans.ser.BigDecimal"); // user type - silly name assertThat(SerTypeMapper.encodeType(lowerCase.class, SETTINGS, "java.util.", cache)).isEqualTo("org.joda.beans.ser.lowerCase"); assertThat(cache.get(lowerCase.class)).isEqualTo("org.joda.beans.ser.lowerCase"); } @Test void test_encodeType_sillyNames() { Map, String> cache = new HashMap<>(); // user type - silly name assertThat(SerTypeMapper.encodeType(BigDecimal.class, SETTINGS, "org.joda.beans.ser.", cache)) .isEqualTo("org.joda.beans.ser.BigDecimal"); assertThat(cache.get(BigDecimal.class)).isEqualTo("org.joda.beans.ser.BigDecimal"); // user type - silly name assertThat(SerTypeMapper.encodeType(lowerCase.class, SETTINGS, "org.joda.beans.ser.", cache)) .isEqualTo("org.joda.beans.ser.lowerCase"); assertThat(cache.get(lowerCase.class)).isEqualTo("org.joda.beans.ser.lowerCase"); } @Test void test_encodeType_noCache() { // user type assertThat(SerTypeMapper.encodeType(AtomicIntegerArray.class, SETTINGS, "java.util.", null)) .isEqualTo("java.util.concurrent.atomic.AtomicIntegerArray"); // user type - second occurrence assertThat(SerTypeMapper.encodeType(AtomicIntegerArray.class, SETTINGS, "java.util.", null)) .isEqualTo("java.util.concurrent.atomic.AtomicIntegerArray"); // user type - normal assertThat(SerTypeMapper.encodeType(Normal.class, SETTINGS, "org.joda.beans.ser.", null)).isEqualTo("Normal"); // user type - silly name assertThat(SerTypeMapper.encodeType(BigDecimal.class, SETTINGS, "org.joda.beans.ser.", null)) .isEqualTo("org.joda.beans.ser.BigDecimal"); // user type - silly name assertThat(SerTypeMapper.encodeType(lowerCase.class, SETTINGS, "org.joda.beans.ser.", null)) .isEqualTo("org.joda.beans.ser.lowerCase"); } @Test void test_encodeType_noBasePackage() { Map, String> cache = new HashMap<>(); // basic type assertThat(SerTypeMapper.encodeType(File.class, SETTINGS, null, cache)).isEqualTo("File"); assertThat(cache).doesNotContainKey(File.class); // user type assertThat(SerTypeMapper.encodeType(AtomicReference.class, SETTINGS, null, cache)) .isEqualTo("java.util.concurrent.atomic.AtomicReference"); assertThat(cache.get(AtomicReference.class)).isEqualTo("AtomicReference"); // user type - second occurrence assertThat(SerTypeMapper.encodeType(AtomicReference.class, SETTINGS, null, cache)).isEqualTo("AtomicReference"); assertThat(cache.get(AtomicReference.class)).isEqualTo("AtomicReference"); } @Test void test_encodeType_noShortTypes() { Map, String> cache = new HashMap<>(); // base package type assertThat(SerTypeMapper.encodeType(BitSet.class, SETTINGS_NO_SHORT, "java.util.", cache)).isEqualTo("java.util.BitSet"); // basic type assertThat(SerTypeMapper.encodeType(File.class, SETTINGS_NO_SHORT, "java.util.", cache)).isEqualTo("File"); // user type assertThat(SerTypeMapper.encodeType(AtomicReference.class, SETTINGS_NO_SHORT, "java.util.", cache)) .isEqualTo("java.util.concurrent.atomic.AtomicReference"); // user type - second occurrence assertThat(SerTypeMapper.encodeType(AtomicReference.class, SETTINGS_NO_SHORT, "java.util.", cache)) .isEqualTo("java.util.concurrent.atomic.AtomicReference"); assertThat(cache).isEmpty(); } //----------------------------------------------------------------------- @Test void test_decodeType() throws Exception { Map> cache = new HashMap<>(); // base package type assertThat(SerTypeMapper.decodeType("BitSet", SETTINGS, "java.util.", cache)).isEqualTo(BitSet.class); assertThat(cache.get("BitSet")).isEqualTo(BitSet.class); // basic type assertThat(SerTypeMapper.decodeType("File", SETTINGS, "java.util.", cache)).isEqualTo(File.class); assertThat(cache).doesNotContainKey("File"); // user type assertThat(SerTypeMapper.decodeType("java.util.concurrent.atomic.AtomicReference", SETTINGS, "java.util.", cache)) .isEqualTo(AtomicReference.class); assertThat(cache.get("java.util.concurrent.atomic.AtomicReference")).isEqualTo(AtomicReference.class); assertThat(cache.get("AtomicReference")).isEqualTo(AtomicReference.class); // user type assertThat(SerTypeMapper.decodeType("AtomicReference", SETTINGS, "java.util.", cache)).isEqualTo(AtomicReference.class); assertThat(cache.get("java.util.concurrent.atomic.AtomicReference")).isEqualTo(AtomicReference.class); assertThat(cache.get("AtomicReference")).isEqualTo(AtomicReference.class); // user type assertThat(SerTypeMapper.decodeType("java.util.concurrent.atomic.AtomicIntegerArray", SETTINGS, "java.util.", cache)) .isEqualTo(AtomicIntegerArray.class); assertThat(cache.get("java.util.concurrent.atomic.AtomicIntegerArray")).isEqualTo(AtomicIntegerArray.class); assertThat(cache.get("AtomicIntegerArray")).isEqualTo(AtomicIntegerArray.class); // user type assertThat(SerTypeMapper.decodeType("AtomicIntegerArray", SETTINGS, "java.util.", cache)).isEqualTo(AtomicIntegerArray.class); assertThat(cache.get("java.util.concurrent.atomic.AtomicIntegerArray")).isEqualTo(AtomicIntegerArray.class); assertThat(cache.get("AtomicIntegerArray")).isEqualTo(AtomicIntegerArray.class); } @Test void test_decodeType_noCache() throws Exception { // base package type assertThat(SerTypeMapper.decodeType("BitSet", SETTINGS, "java.util.", null)).isEqualTo(BitSet.class); // basic type assertThat(SerTypeMapper.decodeType("File", SETTINGS, "java.util.", null)).isEqualTo(File.class); // user type assertThat(SerTypeMapper.decodeType("java.util.concurrent.atomic.AtomicReference", SETTINGS, "java.util.", null)) .isEqualTo(AtomicReference.class); } @Test void test_decodeType_noBasePackage() throws Exception { Map> cache = new HashMap<>(); // basic type assertThat(SerTypeMapper.decodeType("File", SETTINGS, null, cache)).isEqualTo(File.class); // user type assertThat(SerTypeMapper.decodeType("java.util.concurrent.atomic.AtomicReference", SETTINGS, null, cache)) .isEqualTo(AtomicReference.class); } @Test void test_decodeType_emptyClassName() throws Exception { Map> cache = new HashMap<>(); assertThatExceptionOfType(ClassNotFoundException.class) .isThrownBy(() -> SerTypeMapper.decodeType("", SETTINGS, "java.util.", cache)); } } ================================================ FILE: src/test/java/org/joda/beans/ser/TestSerializeSmartReader.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.joda.beans.Bean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmEmpty; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.SimpleJson; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import com.google.common.primitives.Bytes; /** * Test smart reader. */ class TestSerializeSmartReader { @Test void test_binary_address() throws IOException { Address bean = SerTestHelper.testAddress(); byte[] bytes = JodaBeanSer.PRETTY.binWriter().write(bean); Bean roundtrip = JodaBeanSer.PRETTY.smartReader().read(bytes); BeanAssert.assertBeanEquals(bean, roundtrip); } @Test void test_binary_immAddress() throws IOException { ImmAddress bean = SerTestHelper.testImmAddress(false); byte[] bytes = JodaBeanSer.PRETTY.binWriter().write(bean); Bean roundtrip = JodaBeanSer.PRETTY.smartReader().read(bytes); BeanAssert.assertBeanEquals(bean, roundtrip); } @Test void test_binary_optional() throws IOException { ImmOptional bean = SerTestHelper.testImmOptional(); byte[] bytes = JodaBeanSer.PRETTY.binWriter().write(bean); Bean roundtrip = JodaBeanSer.PRETTY.smartReader().read(bytes); BeanAssert.assertBeanEquals(bean, roundtrip); } @Test void test_binary_collections() throws IOException { ImmGuava bean = SerTestHelper.testCollections(true); byte[] bytes = JodaBeanSer.PRETTY.binWriter().write(bean); Bean roundtrip = JodaBeanSer.PRETTY.smartReader().read(bytes); BeanAssert.assertBeanEquals(bean, roundtrip); } //----------------------------------------------------------------------- @Test void test_binaryReferencing_optional() throws IOException { ImmOptional bean = SerTestHelper.testImmOptional(); byte[] bytes = JodaBeanSer.PRETTY.binWriterReferencing().write(bean); Bean roundtrip = JodaBeanSer.PRETTY.smartReader().read(bytes); BeanAssert.assertBeanEquals(bean, roundtrip); } @Test void test_binaryReferencing_collections() throws IOException { ImmGuava bean = SerTestHelper.testCollections(true); byte[] bytes = JodaBeanSer.PRETTY.binWriterReferencing().write(bean); Bean roundtrip = JodaBeanSer.PRETTY.smartReader().read(bytes); BeanAssert.assertBeanEquals(bean, roundtrip); } //----------------------------------------------------------------------- @Test void test_json_address() throws IOException { Address bean = SerTestHelper.testAddress(); String json = JodaBeanSer.PRETTY.jsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, Address.class); } @Test void test_json_immAddress() throws IOException { ImmAddress bean = SerTestHelper.testImmAddress(false); String json = JodaBeanSer.PRETTY.jsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, ImmAddress.class); } @Test void test_json_optional() throws IOException { ImmOptional bean = SerTestHelper.testImmOptional(); String json = JodaBeanSer.PRETTY.jsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, ImmOptional.class); } @Test void test_json_collections() throws IOException { ImmGuava bean = SerTestHelper.testCollections(true); String json = JodaBeanSer.PRETTY.jsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, ImmGuava.class); } @Test void test_json_minimal() throws IOException { assertThat(JodaBeanSer.COMPACT.smartReader().isKnownFormat(new byte[] {'{', '}'})).isTrue(); assertThat(JodaBeanSer.COMPACT.smartReader().isKnownFormat(new byte[] {'{', '\n', ' ', '}'})).isTrue(); } //----------------------------------------------------------------------- @Test void test_simpleJson_empty() throws IOException { ImmEmpty bean = ImmEmpty.builder().build(); String json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, ImmEmpty.class); } @Test void test_simpleJson_basic() throws IOException { SimpleJson bean = SerTestHelper.testSimpleJson(); String json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, SimpleJson.class); } @Test void test_simpleJson_optional() throws IOException { ImmOptional bean = SerTestHelper.testImmOptional(); String json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, ImmOptional.class); } @Test void test_simpleJson_collections() throws IOException { ImmGuava bean = SerTestHelper.testCollections(true); String json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, json, bean, ImmGuava.class); } //----------------------------------------------------------------------- @Test void test_xml_address() throws IOException { Address bean = SerTestHelper.testAddress(); String xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, xml, bean, Address.class); } @Test void test_xml_immAddress() throws IOException { ImmAddress bean = SerTestHelper.testImmAddress(false); String xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, xml, bean, ImmAddress.class); } @Test void test_xml_optional() throws IOException { ImmOptional bean = SerTestHelper.testImmOptional(); String xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, xml, bean, ImmOptional.class); } @Test void test_xml_collections() throws IOException { ImmGuava bean = SerTestHelper.testCollections(true); String xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); assertCharsets(JodaBeanSer.PRETTY, xml, bean, ImmGuava.class); } @Test void test_xml_minimal() throws IOException { byte[] bytes = "".getBytes(StandardCharsets.UTF_8); assertThat(JodaBeanSer.COMPACT.smartReader().isKnownFormat(bytes)).isTrue(); assertThat(JodaBeanSer.COMPACT.smartReader().isKnownFormat(bytes)).isTrue(); } //----------------------------------------------------------------------- private static void assertCharsets(JodaBeanSer settings, String text, T bean, Class type) { byte[] json8Bytes = text.getBytes(StandardCharsets.UTF_8); assertThat(settings.smartReader().isKnownFormat(json8Bytes)).isTrue(); T smart = settings.smartReader().read(json8Bytes, type); BeanAssert.assertBeanEquals(bean, smart); byte[] utf8Bytes = Bytes.concat(new byte[] {(byte) 0xef, (byte) 0xbb, (byte) 0xbf}, json8Bytes); assertThat(settings.smartReader().isKnownFormat(utf8Bytes)).isTrue(); T smart8 = settings.smartReader().read(utf8Bytes, type); BeanAssert.assertBeanEquals(bean, smart8); } //----------------------------------------------------------------------- static Object[][] data_badFormat() { return new Object[][] { {"xml"}, {" JodaBeanSer.COMPACT.smartReader().read(bytes, FlexiBean.class)); } static Object[][] data_unknownFormat() { return new Object[][] { {"xml"}, {") JodaBeanSer.PRETTY.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } private static void assertEqualsSerialization(byte[] actualBytes, String expectedResource) throws IOException { var url = TestSerializePackedBin.class.getResource(expectedResource); var expected = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); var actual = JodaBeanBinReader.visualize(actualBytes); assertThat(actual.trim().replace(lineSeparator(), "\n")).isEqualTo(expected.trim().replace(lineSeparator(), "\n")); } //------------------------------------------------------------------------- @Test void test_writeJodaConvertInterface() { var bean = SerTestHelper.testGenericInterfaces(); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeIntermediateInterface() { var bean = SerTestHelper.testIntermediateInterfaces(); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmKeyList.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeJodaConvert() { // immutable bean that is serialized as joda convert var bean = ImmNamedKey.of("name"); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = (ImmNamedKey) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_readWrite_primitives() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(6); out.writeString("tru"); out.writeBoolean(true); out.writeString("fal"); out.writeBoolean(false); out.writeString("byt"); out.writeByte((byte) 1); out.writeString("sht"); out.writeShort((short) 2); out.writeString("flt"); out.writeFloat(1.2f); out.writeString("dbl"); out.writeDouble(1.8d); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("tru", Boolean.TRUE); bean.set("fal", Boolean.FALSE); bean.set("byt", Byte.valueOf((byte) 1)); bean.set("sht", Short.valueOf((short) 2)); bean.set("flt", Float.valueOf(1.2f)); bean.set("dbl", Double.valueOf(1.8d)); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_primitiveTypeChanged() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); out.writeString("a"); out.writeInt(6); out.writeString("b"); out.writeLong(5); var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmDoubleFloat.class); assertThat(parsed.getA()).isCloseTo(6, offset(1e-10)); assertThat(parsed.getB()).isCloseTo(5, offset(1e-10)); } //------------------------------------------------------------------------- @Test void test_readWrite_booleanAsObject() throws Throwable { assertValueSerializesAsObject(Boolean.TRUE, BeanPack.TRUE, out -> {}); assertValueSerializesAsObject(Boolean.FALSE, BeanPack.FALSE, out -> {}); } @Test void test_readWrite_charAsObject() throws Throwable { assertValueSerializesAsObject(Character.MAX_VALUE, CHAR_16, out -> out.writeChar(Character.MAX_VALUE)); assertValueSerializesAsObject(Character.MIN_VALUE, CHAR_16, out -> out.writeChar(Character.MIN_VALUE)); } @Test void test_readWrite_byteAsObject() throws Throwable { assertValueSerializesAsObject(Byte.MAX_VALUE, BYTE_8, out -> out.writeByte(Byte.MAX_VALUE)); assertValueSerializesAsObject(Byte.MIN_VALUE, BYTE_8, out -> out.writeByte(Byte.MIN_VALUE)); } @Test void test_readWrite_shortAsObject() throws Throwable { assertValueSerializesAsObject(Short.MAX_VALUE, SHORT_16, out -> out.writeShort(Short.MAX_VALUE)); assertValueSerializesAsObject(Short.MIN_VALUE, SHORT_16, out -> out.writeShort(Short.MIN_VALUE)); } @Test void test_readWrite_intAsObject() throws Throwable { assertValueSerializesAsObject(127, 127, out -> {}); assertValueSerializesAsObject(0, 0, out -> {}); assertValueSerializesAsObject(-16, -16, out -> {}); assertValueSerializesAsObject(-17, INT_16, out -> out.writeShort(-17)); assertValueSerializesAsObject(-128, INT_16, out -> out.writeShort(-128)); assertValueSerializesAsObject((int) Short.MAX_VALUE, INT_16, out -> out.writeShort(Short.MAX_VALUE)); assertValueSerializesAsObject((int) Short.MIN_VALUE, INT_16, out -> out.writeShort(Short.MIN_VALUE)); assertValueSerializesAsObject(Integer.MAX_VALUE, INT_32, out -> out.writeInt(Integer.MAX_VALUE)); assertValueSerializesAsObject(Integer.MIN_VALUE, INT_32, out -> out.writeInt(Integer.MIN_VALUE)); } @Test void test_readWrite_longAsObject() throws Throwable { assertValueSerializesAsObject(127L, LONG_8, out -> out.writeByte(127)); assertValueSerializesAsObject(0L, LONG_8, out -> out.writeByte(0)); assertValueSerializesAsObject(-128L, LONG_8, out -> out.writeByte(-128)); assertValueSerializesAsObject((long) Short.MAX_VALUE, LONG_16, out -> out.writeShort(Short.MAX_VALUE)); assertValueSerializesAsObject((long) Short.MIN_VALUE, LONG_16, out -> out.writeShort(Short.MIN_VALUE)); assertValueSerializesAsObject((long) Integer.MAX_VALUE, LONG_32, out -> out.writeInt(Integer.MAX_VALUE)); assertValueSerializesAsObject((long) Integer.MIN_VALUE, LONG_32, out -> out.writeInt(Integer.MIN_VALUE)); assertValueSerializesAsObject(Long.MAX_VALUE, LONG_64, out -> out.writeLong(Long.MAX_VALUE)); assertValueSerializesAsObject(Long.MIN_VALUE, LONG_64, out -> out.writeLong(Long.MIN_VALUE)); } @Test void test_readWrite_floatAsObject() throws Throwable { assertValueSerializesAsObject(Float.MAX_VALUE, FLOAT_32, out -> out.writeFloat(Float.MAX_VALUE)); assertValueSerializesAsObject(Float.MIN_VALUE, FLOAT_32, out -> out.writeFloat(Float.MIN_VALUE)); assertValueSerializesAsObject(Float.NaN, FLOAT_32, out -> out.writeFloat(Float.NaN)); assertValueSerializesAsObject(Float.POSITIVE_INFINITY, FLOAT_32, out -> out.writeFloat(Float.POSITIVE_INFINITY)); assertValueSerializesAsObject(Float.NEGATIVE_INFINITY, FLOAT_32, out -> out.writeFloat(Float.NEGATIVE_INFINITY)); } @Test void test_readWrite_doubleAsObject() throws Throwable { assertValueSerializesAsObject(0d, DOUBLE_INT_8, out -> out.writeByte(0)); assertValueSerializesAsObject((double) 127, DOUBLE_INT_8, out -> out.writeByte(127)); assertValueSerializesAsObject((double) -1, DOUBLE_INT_8, out -> out.writeByte(-1)); assertValueSerializesAsObject((double) -128, DOUBLE_INT_8, out -> out.writeByte(-128)); assertValueSerializesAsObject(-0d, DOUBLE_64, out -> out.writeDouble(-0f)); assertValueSerializesAsObject(1.1d, DOUBLE_64, out -> out.writeDouble(1.1d)); assertValueSerializesAsObject(Double.MAX_VALUE, DOUBLE_64, out -> out.writeDouble(Double.MAX_VALUE)); assertValueSerializesAsObject(Double.MIN_VALUE, DOUBLE_64, out -> out.writeDouble(Double.MIN_VALUE)); assertValueSerializesAsObject(Double.NaN, DOUBLE_64, out -> out.writeDouble(Double.NaN)); assertValueSerializesAsObject(Double.POSITIVE_INFINITY, DOUBLE_64, out -> out.writeDouble(Double.POSITIVE_INFINITY)); assertValueSerializesAsObject(Double.NEGATIVE_INFINITY, DOUBLE_64, out -> out.writeDouble(Double.NEGATIVE_INFINITY)); } @Test void test_readWrite_dateAsObject() throws Throwable { assertValueSerializesAsObject(LocalDate.of(2024, 6, 1), DATE_PACKED, out -> out.writeShort((short) ((24 * 12 + 5 << 5) + 1))); assertValueSerializesAsObject(LocalDate.of(2000, 1, 1), DATE_PACKED, out -> out.writeShort((short) ((0 * 12 + 0 << 5) + 1))); assertValueSerializesAsObject(LocalDate.of(2169, 12, 31), DATE_PACKED, out -> out.writeShort((short) ((169 * 12 + 11 << 5) + 31))); assertValueSerializesAsObject(LocalDate.of(2170, 1, 1), DATE, out -> { out.writeByte((byte) 0); out.writeInt((2170 << 9) + (1 << 5) + 1); }); assertValueSerializesAsObject(LocalDate.of(1999, 12, 31), DATE, out -> { out.writeByte((byte) 0); out.writeInt((1999 << 9) + (12 << 5) + 31); }); assertValueSerializesAsObject(LocalDate.MAX, DATE, out -> { out.writeByte((byte) (999999999 >> 23)); out.writeInt((999999999 << 9) + (12 << 5) + 31); }); assertValueSerializesAsObject(LocalDate.MIN, DATE, out -> { out.writeByte((byte) (-999999999 >> 23)); out.writeInt((-999999999 << 9) + (1 << 5) + 1); }); } @Test void test_readWrite_timeAsObject() throws Throwable { assertValueSerializesAsObject(LocalTime.MAX, TIME, out -> { out.writeShort((short) (LocalTime.MAX.toNanoOfDay() >> 32)); out.writeInt((int) LocalTime.MAX.toNanoOfDay()); }); assertValueSerializesAsObject(LocalTime.MIN, TIME, out -> { out.writeShort((byte) 0); out.writeInt(0); }); } @Test void test_readWrite_instantAsObject() throws Throwable { assertValueSerializesAsObject(Instant.MAX, INSTANT, out -> { out.writeLong(Instant.MAX.getEpochSecond()); out.writeInt(Instant.MAX.getNano()); }); assertValueSerializesAsObject(Instant.EPOCH, INSTANT, out -> { out.writeLong(Instant.EPOCH.getEpochSecond()); out.writeInt(Instant.EPOCH.getNano()); }); assertValueSerializesAsObject(Instant.MIN, INSTANT, out -> { out.writeLong(Instant.MIN.getEpochSecond()); out.writeInt(Instant.MIN.getNano()); }); } @Test void test_readWrite_durationAsObject() throws Throwable { assertValueSerializesAsObject(Duration.ofSeconds(Long.MAX_VALUE, 999_999_999), DURATION, out -> { out.writeLong(Long.MAX_VALUE); out.writeInt(999_999_999); }); assertValueSerializesAsObject(Duration.ofSeconds(Long.MIN_VALUE), DURATION, out -> { out.writeLong(Long.MIN_VALUE); out.writeInt(0); }); } @Test void test_readWrite_stringAsObject() throws Throwable { assertValueSerializesAsObject("", MIN_FIX_STR + 0, out -> {}); assertValueSerializesAsObject("A", MIN_FIX_STR + 1, out -> out.write("A".getBytes(UTF_8))); assertValueSerializesAsObject("A".repeat(12), MIN_FIX_STR + 12, out -> out.write("A".repeat(12).getBytes(UTF_8))); assertValueSerializesAsObject("A".repeat(40), MIN_FIX_STR + 40, out -> out.write("A".repeat(40).getBytes(UTF_8))); assertValueSerializesAsObject("A".repeat(41), STR_8, out -> { out.writeByte(41); out.write("A".repeat(41).getBytes(UTF_8)); }); assertValueSerializesAsObject("A".repeat(255), STR_8, out -> { out.writeByte(255); out.write("A".repeat(255).getBytes(UTF_8)); }); } @Test void test_readWrite_byteArrayAsObject() throws Throwable { assertValueSerializesAsObject(new byte[] {}, BIN_8, out -> out.writeByte(0)); assertValueSerializesAsObject(new byte[] {5}, BIN_8, out -> { out.writeByte(1); out.writeByte(5); }); assertValueSerializesAsObject(new byte[255], BIN_8, out -> { out.writeByte(255); out.write(new byte[255]); }); assertValueSerializesAsObject(new byte[256], BIN_16, out -> { out.writeShort(256); out.write(new byte[256]); }); } @Test void test_readWrite_doubleArrayAsObject() throws Throwable { assertValueSerializesAsObject(new double[] {}, DOUBLE_ARRAY_8, out -> out.writeByte(0)); assertValueSerializesAsObject(new double[] {5.23d}, DOUBLE_ARRAY_8, out -> { out.writeByte(1); out.writeDouble(5.23d); }); assertValueSerializesAsObject(new double[255], DOUBLE_ARRAY_8, out -> { out.writeByte(255); out.write(new byte[255 * 8]); }); assertValueSerializesAsObject(new double[256], DOUBLE_ARRAY_16, out -> { out.writeShort(256); out.write(new byte[256 * 8]); }); } private static void assertValueSerializesAsObject(Object value, int typeByte, ThrowingConsumer fn) throws Throwable { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString("value"); baos.write(typeByte); fn.accept(new DataOutputStream(baos)); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("value", value); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_readWrite_optionalAsObject() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); out.writeString("present"); out.writeTypeReference(BeanPack.TYPE_CODE_OPTIONAL); out.writeArrayHeader(1); out.writeInt(6); out.writeString("empty"); out.writeTypeReference(BeanPack.TYPE_CODE_OPTIONAL); out.writeArrayHeader(0); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("present", Optional.of(6)); bean.set("empty", Optional.empty()); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_stringArrayAsObject() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString("value"); out.writeTypeReference(BeanPack.TYPE_CODE_STRING_ARRAY); out.writeArrayHeader(2); out.writeString("A"); out.writeString("B"); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("value", new String[] {"A", "B"}); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_objectArrayAsObject() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString("value"); out.writeTypeReference(BeanPack.TYPE_CODE_OBJECT_ARRAY); out.writeArrayHeader(2); out.writeString("A"); out.writeInt(6); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("value", new Object[] {"A", 6}); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_intArrayAsObject() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString("value"); out.writeTypeName("int[]"); out.writeArrayHeader(2); out.writeInt(4); out.writeInt(6); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("value", new int[] {4, 6}); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_readWrite_beanValueClass() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(3); out.writeString("value1"); out.writeValueDefinitionHeader(); out.writeTypeName(ImmKey.class.getName()); out.writeBeanDefinitionHeader(1); out.writeString("name"); out.writeString("A"); out.writeString("value2"); out.writeValueDefinitionHeader(); out.writeTypeReference(0); out.writeArrayHeader(1); out.writeString("B"); out.writeString("value3"); out.writeValueReference(2); var expected = baos.toByteArray(); var bean = new FlexiBean(); bean.set("value1", ImmKey.builder().name("A").build()); bean.set("value2", ImmKey.builder().name("B").build()); bean.set("value3", ImmKey.builder().name("A").build()); var bytes = JodaBeanSer.COMPACT.withBeanValueClasses(Set.of(ImmKey.class)).binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); assertThat(parsed.get("value1")).isSameAs(parsed.get("value3")); } //------------------------------------------------------------------------- @Test void test_readWrite_sparseGridAsObject() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString("value"); out.writeTypeReference(TYPE_CODE_GRID); out.writeArrayHeader(3); out.writeInt(4); out.writeInt(2); out.writeArrayHeader(6); out.writeInt(0); out.writeInt(1); out.writeString("A"); out.writeInt(1); out.writeInt(0); out.writeString("B"); var expected = baos.toByteArray(); var grid = SparseGrid.create(4, 2); grid.put(0, 1, "A"); grid.put(1, 0, "B"); var bean = new FlexiBean(); bean.set("value", grid); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_denseGridAsObject() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString("value"); out.writeTypeReference(TYPE_CODE_GRID); out.writeArrayHeader(3); out.writeInt(-2); out.writeInt(2); out.writeArrayHeader(4); out.writeNull(); out.writeString("A"); out.writeString("B"); out.writeNull(); var expected = baos.toByteArray(); var grid = DenseGrid.create(2, 2); grid.put(0, 1, "A"); grid.put(1, 0, "B"); var bean = new FlexiBean(); bean.set("value", grid); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_read_typeConvertToDouble() throws Throwable { var bean = new PrimitiveBean(); bean.setValueDouble(126); assertIntegralConvert(bean, "valueDouble", out -> out.writeLong(126)); assertIntegralConvert(bean, "valueDouble", out -> out.writeInt(126)); assertIntegralConvert(bean, "valueDouble", out -> out.writeShort((short) 126)); assertIntegralConvert(bean, "valueDouble", out -> out.writeByte((byte) 126)); } @Test void test_read_typeConvertToFloat() throws Throwable { var bean = new PrimitiveBean(); bean.setValueFloat(126); assertIntegralConvert(bean, "valueFloat", out -> out.writeLong(126)); assertIntegralConvert(bean, "valueFloat", out -> out.writeInt(126)); assertIntegralConvert(bean, "valueFloat", out -> out.writeShort((short) 126)); assertIntegralConvert(bean, "valueFloat", out -> out.writeByte((byte) 126)); } @Test void test_read_typeConvertToLong() throws Throwable { var bean = new PrimitiveBean(); bean.setValueLong(126); assertIntegralConvert(bean, "valueLong", out -> out.writeLong(126)); assertIntegralConvert(bean, "valueLong", out -> out.writeInt(126)); assertIntegralConvert(bean, "valueLong", out -> out.writeShort((short) 126)); assertIntegralConvert(bean, "valueLong", out -> out.writeByte((byte) 126)); } @Test void test_read_typeConvertToInt() throws Throwable { var bean = new PrimitiveBean(); bean.setValueInt(126); assertIntegralConvert(bean, "valueInt", out -> out.writeLong(126)); assertIntegralConvert(bean, "valueInt", out -> out.writeInt(126)); assertIntegralConvert(bean, "valueInt", out -> out.writeShort((short) 126)); assertIntegralConvert(bean, "valueInt", out -> out.writeByte((byte) 126)); assertIntegralConvertBad("valueInt", out -> out.writeLong(((long) Integer.MAX_VALUE) + 1)); assertIntegralConvertBad("valueInt", out -> out.writeLong(((long) Integer.MIN_VALUE) - 1)); } @Test void test_read_typeConvertToShort() throws Throwable { var bean = new PrimitiveBean(); bean.setValueShort((short) 126); assertIntegralConvert(bean, "valueShort", out -> out.writeLong(126)); assertIntegralConvert(bean, "valueShort", out -> out.writeInt(126)); assertIntegralConvert(bean, "valueShort", out -> out.writeShort((short) 126)); assertIntegralConvert(bean, "valueShort", out -> out.writeByte((byte) 126)); assertIntegralConvertBad("valueShort", out -> out.writeInt(Short.MAX_VALUE + 1)); assertIntegralConvertBad("valueShort", out -> out.writeInt(Short.MIN_VALUE - 1)); assertIntegralConvertBad("valueShort", out -> out.writeLong(((long) Short.MAX_VALUE) + 1)); assertIntegralConvertBad("valueShort", out -> out.writeLong(((long) Short.MIN_VALUE) - 1)); } @Test void test_read_typeConvertToByte() throws Throwable { var bean = new PrimitiveBean(); bean.setValueByte((byte) 126); assertIntegralConvert(bean, "valueByte", out -> out.writeLong(126)); assertIntegralConvert(bean, "valueByte", out -> out.writeInt(126)); assertIntegralConvert(bean, "valueByte", out -> out.writeShort((short) 126)); assertIntegralConvert(bean, "valueByte", out -> out.writeByte((byte) 126)); assertIntegralConvertBad("valueByte", out -> out.writeLong(128)); assertIntegralConvertBad("valueByte", out -> out.writeLong(-129)); assertIntegralConvertBad("valueByte", out -> out.writeInt(128)); assertIntegralConvertBad("valueByte", out -> out.writeInt(-129)); assertIntegralConvertBad("valueByte", out -> out.writeShort((short) 128)); assertIntegralConvertBad("valueByte", out -> out.writeShort((short) -129)); } private static void assertIntegralConvert(PrimitiveBean bean, String fieldName, ThrowingConsumer outFn) throws Throwable { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString(fieldName); outFn.accept(out); BeanAssert.assertBeanEquals(bean, JodaBeanSer.COMPACT.binReader().read(baos.toByteArray(), PrimitiveBean.class)); } private static void assertIntegralConvertBad(String fieldName, ThrowingConsumer outFn) throws Throwable { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(1); out.writeString(fieldName); outFn.accept(out); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(baos.toByteArray(), PrimitiveBean.class)); } //------------------------------------------------------------------------- @Test void test_read_beanProperty_typeDefinitionInRemovedSubTree_explicitPropertyType() throws Throwable { var bean = new Pair(); bean.setFirst(RiskLevel.HIGH); var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); // property 'Pair#removed' of type TupleFinal out.writeString("removed"); out.writeTypeName(TupleFinal.class.getName()); // removed property defined with explicit type out.writeMapHeader(1); out.writeString("first"); out.writeTypeName(RiskLevel.class.getName()); out.writeString("LOW"); // property 'Pair#first' of type RiskLevel out.writeString("first"); out.writeValueDefinitionHeader(); out.writeTypeReference(1); out.writeString(RiskLevel.HIGH.name()); var ser = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); BeanAssert.assertBeanEquals(bean, ser.binReader().read(baos.toByteArray(), Pair.class)); } @Test void test_read_beanProperty_typeDefinitionInRemovedSubTree_inferredPropertyTypeForBeanInMapFormat() throws Throwable { var bean = new Pair(); bean.setFirst(RiskLevel.HIGH); var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); // property 'Pair#removed' where the removed property was used to infer the type out.writeString("removed"); out.writeMapHeader(1); out.writeString("first"); out.writeTypeName(RiskLevel.class.getName()); out.writeString("LOW"); // property 'Pair#first' of type RiskLevel out.writeString("first"); out.writeValueDefinitionHeader(); out.writeTypeReference(0); out.writeString(RiskLevel.HIGH.name()); var ser = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); BeanAssert.assertBeanEquals(bean, ser.binReader().read(baos.toByteArray(), Pair.class)); } @Test void test_read_beanProperty_typeDefinitionInRemovedSubTree_inferredPropertyTypeForBeanInArrayFormat() throws Throwable { var bean = new Pair(); bean.setFirst(RiskLevel.HIGH); var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); // property 'Pair#removed' where the removed property was used to infer the type out.writeString("removed"); out.writeArrayHeader(1); // note that in reality there would have been a bean definition somewhere out.writeTypeName(RiskLevel.class.getName()); out.writeString("LOW"); // property 'Pair#first' of type RiskLevel out.writeString("first"); out.writeValueDefinitionHeader(); out.writeTypeReference(0); out.writeString(RiskLevel.HIGH.name()); var ser = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); BeanAssert.assertBeanEquals(bean, ser.binReader().read(baos.toByteArray(), Pair.class)); } @Test void test_read_beanProperty_typeDefinitionInRemovedSubTree_typeNoLongerExistsButIsNotReferenced() throws Throwable { var bean = new Pair(); bean.setFirst(RiskLevel.HIGH); var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); // property 'Pair#removed' where the removed property was used to infer the type out.writeString("removed"); out.writeArrayHeader(1); // note that in reality there would have been a bean definition somewhere out.writeTypeName("my.BadType"); out.writeString("LOW"); // property 'Pair#first' of type RiskLevel out.writeString("first"); out.writeValueDefinitionHeader(); out.writeTypeName(RiskLevel.class.getName()); out.writeString(RiskLevel.HIGH.name()); var ser = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); BeanAssert.assertBeanEquals(bean, ser.binReader().read(baos.toByteArray(), Pair.class)); } @Test void test_read_beanProperty_beanAndValueDefinitionInRemovedSubTree() throws Throwable { var bean = new Pair(); var subPair = new Pair(); bean.setFirst(subPair); subPair.setFirst(2.5d); subPair.setSecond(1.5d); var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); // property 'Pair#removed' out.writeString("removed"); out.writeTypeName(Pair.class.getName()); out.writeBeanDefinitionHeader(2); out.writeString("first"); out.writeString("second"); out.writeValueDefinitionHeader(); out.writeDouble(1.5d); out.writeValueDefinitionHeader(); out.writeDouble(2.5d); // property 'Pair#first' of type Pair out.writeString("first"); out.writeTypeReference(0); out.writeArrayHeader(2); out.writeValueReference(4); out.writeValueReference(3); var ser = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); BeanAssert.assertBeanEquals(bean, ser.binReader().read(baos.toByteArray(), Pair.class)); } //------------------------------------------------------------------------- @Test void test_read_arrayMultidimensional() throws Throwable { var bean = new Pair(); bean.setFirst(new String[][] {{"1", "2"}, {"3"}}); bean.setSecond(new Number[][][] {{{1}, {2.5}}, {{3}}}); var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); // property 'Pair#first' out.writeString("first"); out.writeTypeName("String[][]"); out.writeArrayHeader(2); out.writeArrayHeader(2); out.writeString("1"); out.writeString("2"); out.writeArrayHeader(1); out.writeString("3"); // property 'Pair#second' out.writeString("second"); out.writeTypeName("java.lang.Number[][][]"); out.writeArrayHeader(2); out.writeArrayHeader(2); out.writeArrayHeader(1); out.writeInt(1); out.writeArrayHeader(1); out.writeDouble(2.5d); out.writeArrayHeader(1); out.writeArrayHeader(1); out.writeInt(3); var ser = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT); BeanAssert.assertBeanEquals(bean, ser.binReader().read(baos.toByteArray(), Pair.class)); } //------------------------------------------------------------------------- @Test void test_read_optionalTypeToDefaulted() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeString(""); out.writeMapHeader(0); var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmDefault.class); assertThat(parsed.getValue()).isEqualTo("Defaulted"); } @Test void test_readWriteJodaConvertWrapper() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); out.writeString("bean"); out.writeValueDefinitionHeader(); out.writeTypeName(JodaConvertBean.class.getName()); out.writeString("Hello:9"); out.writeString("description"); out.writeString("Weird"); var expected = baos.toByteArray(); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(wrapper, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertWrapper.class); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_readWriteJodaConvertBean() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); out.writeString("base"); out.writeString("Hello"); out.writeString("extra"); out.writeInt(9); var expected = baos.toByteArray(); var bean = new JodaConvertBean("Hello:9"); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_JodaConvertWrapper_beanNotJodaConvertAndNoDefinition() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); out.writeString("bean"); out.writeMapHeader(2); out.writeString("base"); out.writeString("Hello"); out.writeString("extra"); out.writeInt(9); out.writeString("description"); out.writeString("Weird"); var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertWrapper.class); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_read_JodaConvertWrapper_beanJodaConvert() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(2); out.writeString("bean"); out.writeString("Hello:9"); out.writeString("description"); out.writeString("Weird"); var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertWrapper.class); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); BeanAssert.assertBeanEquals(wrapper, parsed); } //----------------------------------------------------------------------- @Test void test_read_invalidFormat_sizeOneArrayAtRoot() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(1); out.writeInt(3); var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_read_wrongVersion() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(0); out.writeNull(); out.writeMapHeader(0); var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_read_rootTypeNotSpecified_FlexiBean() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(0); var bytes = baos.toByteArray(); assertThatNoException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_read_rootTypeNotSpecified_Bean() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeMapHeader(0); var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class)); } @Test void test_read_rootTypeValid_Bean() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeTypeName(FlexiBean.class.getName()); out.writeMapHeader(0); var bytes = baos.toByteArray(); assertThatNoException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class)); } @Test void test_read_rootTypeInvalid_Bean() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeTypeName(String.class.getName()); out.writeMapHeader(0); var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class)); } @Test void test_read_rootTypeInvalid_incompatible() throws IOException { var baos = new ByteArrayOutputStream(); var out = new BeanPackOutput(baos); out.writeArrayHeader(3); out.writeInt(3); out.writeNull(); out.writeTypeName(Company.class.getName()); var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_write_nullKeyInMap() { var address = new Address(); var bean = new Person(); bean.getOtherAddressMap().put(null, address); var bytes = JodaBeanSer.COMPACT.binWriter(PACKED).write(bean); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes); assertThat(parsed).isEqualTo(bean); } } ================================================ FILE: src/test/java/org/joda/beans/ser/bin/TestSerializeReferencingBin.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import static java.lang.System.lineSeparator; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.assertj.core.api.Assertions.offset; import static org.joda.beans.ser.bin.JodaBeanBinFormat.REFERENCING; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Map; import org.joda.beans.ImmutableBean; import org.joda.beans.sample.Company; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmArrays; import org.joda.beans.sample.ImmDefault; import org.joda.beans.sample.ImmDoubleFloat; import org.joda.beans.sample.ImmGeneric; import org.joda.beans.sample.ImmGenericArray; import org.joda.beans.sample.ImmGenericCollections; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmJodaConvertBean; import org.joda.beans.sample.ImmJodaConvertWrapper; import org.joda.beans.sample.ImmKeyHolder; import org.joda.beans.sample.ImmKeyList; import org.joda.beans.sample.ImmNamedKey; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.ImmTreeNode; import org.joda.beans.sample.JodaConvertInterface; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTestHelper; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import com.google.common.io.Resources; /** * Test property roundtrip using referencing binary. */ class TestSerializeReferencingBin { @Test void test_writeImmAddress() throws IOException { var bean = SerTestHelper.testImmAddress(true); var bytes = JodaBeanSer.PRETTY.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/ImmAddress1.refbinstr"); var parsed = (ImmAddress) JodaBeanSer.PRETTY.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmOptional() throws IOException { // derived properties are not supported var bean = SerTestHelper.testImmOptional(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/ImmOptional1.refbinstr"); var parsed = (ImmOptional) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmArrays() throws IOException { var bean = ImmArrays.of( new int[] {1, 3, 2}, new long[] {1, 4, 3}, new double[] {1.1, 2.2, 3.3}, new boolean[] {true, false}, new int[][] {{1, 2}, {2}, {}}, new boolean[][] {{true, false}, {false}, {}}); var bytes = JodaBeanSer.PRETTY.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/ImmArrays1.refbinstr"); var parsed = JodaBeanSer.PRETTY.binReader().read(bytes, ImmArrays.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeCollections() throws IOException { var bean = SerTestHelper.testCollections(true); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/Collections1.refbinstr"); @SuppressWarnings("unchecked") var parsed = (ImmGuava) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } private void assertEqualsSerialization(byte[] actualBytes, String expectedResource) throws IOException { var url = TestSerializeReferencingBin.class.getResource(expectedResource); var expected = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); var actual = new MsgPackVisualizer(actualBytes).visualizeData(); assertThat(actual.trim().replace(lineSeparator(), "\n")).isEqualTo(expected.trim().replace(lineSeparator(), "\n")); } //------------------------------------------------------------------------- @Test void test_writeJodaConvertInterface() { var bean = SerTestHelper.testGenericInterfaces(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); @SuppressWarnings("unchecked") var parsed = (ImmGenericCollections) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeJodaConvertInterfaceCollections() { var bean = SerTestHelper.testGenericInterfacesCollections(); var bytes = JodaBeanSer.COMPACT.binWriterReferencing().write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(parsed, bean); } @Test void test_writeIntermediateInterface() { var bean = SerTestHelper.testIntermediateInterfaces(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmKeyList.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeJodaConvert() { // immutable bean that is serialized as joda convert var bean = ImmNamedKey.of("name"); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = (ImmNamedKey) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeGenericCollections() { var bean = SerTestHelper.testGenericNestedCollections(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); @SuppressWarnings("unchecked") var parsed = (ImmGenericCollections>) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeFirstInstanceOfBeanHasNullProperties() { var bean = SerTestHelper.testGenericArrayWithNulls(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); @SuppressWarnings("unchecked") var parsed = (ImmGenericArray>) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeTree() { var bean = SerTestHelper.testTree(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); var regularBytes = JodaBeanSer.COMPACT.binWriter().write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = (ImmTreeNode) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); assertThat((double) bytes.length).isLessThan(regularBytes.length / 2d); } //------------------------------------------------------------------------- @Test void test_read_deserializerReferencesUnseenClass() { var immKeyHolder = SerTestHelper.testImmKeyHolder(); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(immKeyHolder); var bean = (ImmKeyHolder) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, immKeyHolder); } @Test void test_read_primitiveTypeChanged() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); // version out.writeByte(0); // refs //classes out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.STR_8); out.writeByte(ImmDoubleFloat.class.getName().length()); out.writeBytes(ImmDoubleFloat.class.getName()); out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(MsgPack.MIN_FIX_STR + 1); out.writeBytes("a"); out.writeByte(MsgPack.MIN_FIX_STR + 1); out.writeBytes("b"); // Data out.writeByte(MsgPack.MIN_FIX_ARRAY + 3); out.writeByte(MsgPack.FIX_EXT_1); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.writeByte(0); // First class out.writeByte(6); // a out.writeByte(5); // b } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmDoubleFloat.class); assertThat(parsed.getA()).isCloseTo(6, offset(1e-10)); assertThat(parsed.getB()).isCloseTo(5, offset(1e-10)); } @Test void test_read_optionalTypeToDefaulted() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); // version out.writeByte(0); // refs //classes out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.STR_8); out.writeByte(ImmDefault.class.getName().length()); out.writeBytes(ImmDefault.class.getName()); out.writeByte(MsgPack.MIN_FIX_ARRAY + 1); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("value"); // Data out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(MsgPack.FIX_EXT_1); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.writeByte(0); out.writeByte(MsgPack.NIL); // value not set } var bytes = baos.toByteArray(); ImmDefault parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmDefault.class); assertThat(parsed.getValue()).isEqualTo("Defaulted"); } @Test void test_read_wrongVersion() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(-1); } var bytes = baos.toByteArray(); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, ImmDoubleFloat.class)); } @Test void test_read_wrongVersionTooHigh() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(3); } var bytes = baos.toByteArray(); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, ImmDoubleFloat.class)); } //----------------------------------------------------------------------- @Test void test_readWriteJodaConvertWrapper() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.STR_8); out.writeByte(ImmJodaConvertWrapper.class.getName().length()); out.writeBytes(ImmJodaConvertWrapper.class.getName()); out.write(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("bean"); out.writeByte(MsgPack.MIN_FIX_STR + 11); out.writeBytes("description"); out.writeByte(MsgPack.MIN_FIX_ARRAY + 3); out.writeByte(MsgPack.FIX_EXT_1); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_STR + 7); out.writeBytes("Hello:9"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Weird"); } var expected = baos.toByteArray(); var bean = new ImmJodaConvertBean("Hello:9"); var wrapper = ImmJodaConvertWrapper.of(bean, "Weird"); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(wrapper); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmJodaConvertWrapper.class); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_readWriteJodaConvertBean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.STR_8); out.writeByte(ImmJodaConvertBean.class.getName().length()); out.writeBytes(ImmJodaConvertBean.class.getName()); out.write(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("base"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("extra"); out.writeByte(MsgPack.MIN_FIX_ARRAY + 3); out.writeByte(MsgPack.FIX_EXT_1); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Hello"); out.writeByte(9); } var expected = baos.toByteArray(); var bean = new ImmJodaConvertBean("Hello:9"); var bytes = JodaBeanSer.COMPACT.binWriter(REFERENCING).write(bean); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmJodaConvertBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_nonStandard_JodaConvertWrapper_expanded() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_MAP + 2); out.writeByte(MsgPack.STR_8); out.writeByte(ImmJodaConvertWrapper.class.getName().length()); out.writeBytes(ImmJodaConvertWrapper.class.getName()); out.write(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("bean"); out.writeByte(MsgPack.MIN_FIX_STR + 11); out.writeBytes("description"); out.writeByte(MsgPack.STR_8); out.writeByte(ImmJodaConvertBean.class.getName().length()); out.writeBytes(ImmJodaConvertBean.class.getName()); out.write(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("base"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("extra"); out.writeByte(MsgPack.MIN_FIX_ARRAY + 3); out.writeByte(MsgPack.FIX_EXT_1); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_ARRAY + 3); out.writeByte(MsgPack.FIX_EXT_1); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Hello"); out.writeByte(9); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Weird"); } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmJodaConvertWrapper.class); var bean = new ImmJodaConvertBean("Hello:9"); var wrapper = ImmJodaConvertWrapper.of(bean, "Weird"); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_read_nonStandard_JodaConvertBean_flattened() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_MAP); out.writeByte(MsgPack.MIN_FIX_STR + 7); out.writeBytes("Hello:9"); } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmJodaConvertBean.class); var bean = new ImmJodaConvertBean("Hello:9"); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_invalidFormat_sizeOneArrayAtRoot() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 1); out.writeByte(2); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, ImmJodaConvertBean.class)); } @Test void test_read_rootTypeNotSpecified_Bean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, ImmutableBean.class)); } @Test void test_read_rootTypeInvalid_Bean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(String.class.getName().length()); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.write(String.class.getName().getBytes(MsgPack.UTF_8)); out.writeByte(MsgPack.NIL); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, ImmutableBean.class)); } @Test void test_read_rootTypeInvalid_incompatible() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 4); out.writeByte(2); out.writeByte(0); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.STR_8); out.writeByte(Company.class.getName().length()); out.write(Company.class.getName().getBytes(MsgPack.UTF_8)); out.writeByte(MsgPack.MIN_FIX_ARRAY + 1); out.writeByte(MsgPack.STR_8); var companyName = "companyName".getBytes(MsgPack.UTF_8); out.write(companyName.length); out.write(companyName); out.writeByte(MsgPack.MIN_FIX_ARRAY + 1); out.write(MsgPack.NIL); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, ImmJodaConvertBean.class)); } } ================================================ FILE: src/test/java/org/joda/beans/ser/bin/TestSerializeStandardBin.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.bin; import static java.lang.System.lineSeparator; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.assertj.core.api.Assertions.offset; import static org.joda.beans.ser.bin.JodaBeanBinFormat.STANDARD; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.joda.beans.Bean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.Company; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmArrays; import org.joda.beans.sample.ImmDefault; import org.joda.beans.sample.ImmDoubleFloat; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmKeyList; import org.joda.beans.sample.ImmNamedKey; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.JodaConvertBean; import org.joda.beans.sample.JodaConvertWrapper; import org.joda.beans.sample.Person; import org.joda.beans.sample.SimpleJson; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTestHelper; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableList; import com.google.common.io.Resources; /** * Test property roundtrip using binary. */ class TestSerializeStandardBin { @Test void test_writeAddress() throws IOException { var bean = SerTestHelper.testAddress(); var bytes = JodaBeanSer.PRETTY.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/Address2.binstr"); var parsed = (Address) JodaBeanSer.PRETTY.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmAddress() throws IOException { var bean = SerTestHelper.testImmAddress(false); var bytes = JodaBeanSer.PRETTY.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/ImmAddress2.binstr"); var parsed = (ImmAddress) JodaBeanSer.PRETTY.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); // old format in /org/joda/beans/ser/ImmAddress1 is indirectly tested in test_readOldStringArrayWithMetaFormat() } @Test void test_writeImmOptional() throws IOException { var bean = SerTestHelper.testImmOptional(); var bytes = JodaBeanSer.PRETTY.withIncludeDerived(true).binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/ImmOptional2.binstr"); var parsed = (ImmOptional) JodaBeanSer.PRETTY.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmArrays() throws IOException { var bean = ImmArrays.of( new int[] {1, 3, 2}, new long[] {1, 4, 3}, new double[] {1.1, 2.2, 3.3}, new boolean[] {true, false}, new int[][] {{1, 2}, {2}, {}}, new boolean[][] {{true, false}, {false}, {}}); var bytes = JodaBeanSer.PRETTY.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/ImmArrays2.binstr"); var parsed = JodaBeanSer.PRETTY.binReader().read(bytes, ImmArrays.class); BeanAssert.assertBeanEquals(bean, parsed); // old format in /org/joda/beans/ser/ImmArrays1 is indirectly tested in test_readOldPrimitiveArrayFormat() } @Test void test_writeCollections() throws IOException { var bean = SerTestHelper.testCollections(true); var bytes = JodaBeanSer.PRETTY.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); assertEqualsSerialization(bytes, "/org/joda/beans/ser/Collections2.binstr"); @SuppressWarnings("unchecked") var parsed = (ImmGuava) JodaBeanSer.PRETTY.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); // old format in /org/joda/beans/ser/Collections1 is indirectly tested in test_readOldListWithMetaFormat() } private void assertEqualsSerialization(byte[] actualBytes, String expectedResource) throws IOException { var url = TestSerializeStandardBin.class.getResource(expectedResource); var expected = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); var actual = new MsgPackVisualizer(actualBytes).visualizeData(); assertThat(actual.trim().replace(lineSeparator(), "\n")).isEqualTo(expected.trim().replace(lineSeparator(), "\n")); } //------------------------------------------------------------------------- @Test void test_writeJodaConvertInterface() { var bean = SerTestHelper.testGenericInterfaces(); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeIntermediateInterface() { var bean = SerTestHelper.testIntermediateInterfaces(); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmKeyList.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeJodaConvert() { // immutable bean that is serialized as joda convert var bean = ImmNamedKey.of("name"); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(bean); // System.out.println(JodaBeanBinReader.visualize(bytes)); var parsed = (ImmNamedKey) JodaBeanSer.COMPACT.binReader().read(bytes); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_readWrite_primitives() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 6); out.writeByte(MsgPack.MIN_FIX_STR + 3); out.writeBytes("tru"); out.writeByte(MsgPack.TRUE); out.writeByte(MsgPack.MIN_FIX_STR + 3); out.writeBytes("fal"); out.writeByte(MsgPack.FALSE); out.writeByte(MsgPack.MIN_FIX_STR + 3); out.writeBytes("byt"); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(4); out.writeByte(MsgPack.JODA_TYPE_DATA); out.writeBytes("Byte"); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_STR + 3); out.writeBytes("sht"); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(5); out.writeByte(MsgPack.JODA_TYPE_DATA); out.writeBytes("Short"); out.writeByte(2); out.writeByte(MsgPack.MIN_FIX_STR + 3); out.writeBytes("flt"); out.writeByte(MsgPack.FLOAT_32); out.writeFloat(1.2f); out.writeByte(MsgPack.MIN_FIX_STR + 3); out.writeBytes("dbl"); out.writeByte(MsgPack.FLOAT_64); out.writeDouble(1.8d); } var expected = baos.toByteArray(); FlexiBean bean = new FlexiBean(); bean.set("tru", Boolean.TRUE); bean.set("fal", Boolean.FALSE); bean.set("byt", Byte.valueOf((byte) 1)); bean.set("sht", Short.valueOf((short) 2)); bean.set("flt", Float.valueOf(1.2f)); bean.set("dbl", Double.valueOf(1.8d)); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_primitiveTypeChanged() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 2); out.writeByte(MsgPack.MIN_FIX_STR + 1); out.writeBytes("a"); out.writeByte(6); out.writeByte(MsgPack.MIN_FIX_STR + 1); out.writeBytes("b"); out.writeByte(5); } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmDoubleFloat.class); assertThat(parsed.getA()).isCloseTo(6, offset(1e-10)); assertThat(parsed.getB()).isCloseTo(5, offset(1e-10)); } @Test void test_read_optionalTypeToDefaulted() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP); } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmDefault.class); assertThat(parsed.getValue()).isEqualTo("Defaulted"); } @Test void test_readWriteJodaConvertWrapper() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("bean"); out.writeByte(MsgPack.MIN_FIX_STR + 7); out.writeBytes("Hello:9"); out.writeByte(MsgPack.MIN_FIX_STR + 11); out.writeBytes("description"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Weird"); } var expected = baos.toByteArray(); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(wrapper, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertWrapper.class); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_readWriteJodaConvertBean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("base"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Hello"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("extra"); out.writeByte(9); } var expected = baos.toByteArray(); var bean = new JodaConvertBean("Hello:9"); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(bean, false); assertThat(bytes).isEqualTo(expected); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_readOldPrimitiveArrayFormat() throws IOException { // test format written by v2.12 can still be read var baos = new ByteArrayOutputStream(); var out = new MsgPackOutput(baos); out.writeArrayHeader(2); out.writeInt(1); out.writeMapHeader(2); out.writeString("intArray"); out.writeString("1,3,2"); out.writeString("intArray2d"); out.writeArrayHeader(3); out.writeString("1,2"); out.writeString("2"); out.writeString(""); var bytes = baos.toByteArray(); var expected = ImmArrays.builder() .intArray(1, 3, 2) .intArray2d(new int[][] {{1, 2}, {2}, {}}) .build(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmArrays.class); BeanAssert.assertBeanEquals(expected, parsed); } @Test void test_readOldStringArrayWithMetaFormat() throws IOException { // test format written by v2.12 can still be read var baos = new ByteArrayOutputStream(); var out = new MsgPackOutput(baos); out.writeArrayHeader(2); out.writeInt(1); out.writeMapHeader(1); out.writeString("array2d"); out.writeMapHeader(1); out.writeExtensionString(MsgPack.JODA_TYPE_META, "String[][]"); out.writeArrayHeader(3); out.writeMapHeader(1); out.writeExtensionString(MsgPack.JODA_TYPE_META, "String[]"); out.writeArrayHeader(1); out.writeString("a"); out.writeMapHeader(1); out.writeExtensionString(MsgPack.JODA_TYPE_META, "String[]"); out.writeArrayHeader(0); out.writeMapHeader(1); out.writeExtensionString(MsgPack.JODA_TYPE_META, "String[]"); out.writeArrayHeader(2); out.writeString("b"); out.writeString("c"); var bytes = baos.toByteArray(); var expected = SimpleJson.builder() .array2d(new String[][] {{"a"}, {}, {"b", "c"}}) .build(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, SimpleJson.class); BeanAssert.assertBeanEquals(expected, parsed); } @Test > void test_readOldListWithMetaFormat() throws IOException { // test format written by v2.12 can still be read (meta caused by List declaration) var baos = new ByteArrayOutputStream(); var out = new MsgPackOutput(baos); out.writeArrayHeader(2); out.writeInt(1); out.writeMapHeader(1); out.writeString("list"); out.writeArrayHeader(2); out.writeMapHeader(1); out.writeExtensionString(MsgPack.JODA_TYPE_DATA, "String"); out.writeString("A"); out.writeMapHeader(1); out.writeExtensionString(MsgPack.JODA_TYPE_DATA, "String"); out.writeString("B"); var bytes = baos.toByteArray(); @SuppressWarnings("unchecked") var list = (ImmutableList) ImmutableList.of("A", "B"); var expected = ImmGuava.builder() .list(list) .build(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, ImmGuava.class); BeanAssert.assertBeanEquals(expected, parsed); } //----------------------------------------------------------------------- @Test void test_read_nonStandard_JodaConvertWrapper_expanded() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("bean"); out.writeByte(MsgPack.MIN_FIX_MAP + 2); out.writeByte(MsgPack.MIN_FIX_STR + 4); out.writeBytes("base"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Hello"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("extra"); out.writeByte(9); out.writeByte(MsgPack.MIN_FIX_STR + 11); out.writeBytes("description"); out.writeByte(MsgPack.MIN_FIX_STR + 5); out.writeBytes("Weird"); } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertWrapper.class); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_read_nonStandard_JodaConvertBean_flattened() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_STR + 7); out.writeBytes("Hello:9"); out.writeByte(9); } var bytes = baos.toByteArray(); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes, JodaConvertBean.class); var bean = new JodaConvertBean("Hello:9"); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_invalidFormat_sizeOneArrayAtRoot() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 1); out.writeByte(1); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_read_wrongVersion() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(-1); out.writeByte(MsgPack.MIN_FIX_MAP + 0); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_read_rootTypeNotSpecified_FlexiBean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 0); } var bytes = baos.toByteArray(); JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class); } @Test void test_read_rootTypeNotSpecified_Bean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 0); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class)); } @Test void test_read_rootTypeValid_Bean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(FlexiBean.class.getName().length()); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.write(FlexiBean.class.getName().getBytes(MsgPack.UTF_8)); out.writeByte(MsgPack.NIL); } var bytes = baos.toByteArray(); JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class); } @Test void test_read_rootTypeInvalid_Bean() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(String.class.getName().length()); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.write(String.class.getName().getBytes(MsgPack.UTF_8)); out.writeByte(MsgPack.NIL); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class)); } @Test void test_read_rootTypeInvalid_incompatible() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(Company.class.getName().length()); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.write(Company.class.getName().getBytes(MsgPack.UTF_8)); out.writeByte(MsgPack.NIL); } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, FlexiBean.class)); } @Test void test_read_invalidFormat_noNilValueAfterType() throws IOException { var baos = new ByteArrayOutputStream(); try (var out = new DataOutputStream(baos)) { out.writeByte(MsgPack.MIN_FIX_ARRAY + 2); out.writeByte(1); out.writeByte(MsgPack.MIN_FIX_MAP + 1); out.writeByte(MsgPack.EXT_8); out.writeByte(FlexiBean.class.getName().length()); out.writeByte(MsgPack.JODA_TYPE_BEAN); out.write(FlexiBean.class.getName().getBytes(MsgPack.UTF_8)); out.writeByte(MsgPack.TRUE); // should be NIL } var bytes = baos.toByteArray(); assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read(bytes, Bean.class)); } @Test void test_read_byteArray_nullByteArray() { assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.binReader().read((byte[]) null, Company.class)); } @Test void test_write_nullKeyInMap() { var address = new Address(); var bean = new Person(); bean.getOtherAddressMap().put(null, address); var bytes = JodaBeanSer.COMPACT.binWriter(STANDARD).write(bean); var parsed = JodaBeanSer.COMPACT.binReader().read(bytes); assertThat(parsed).isEqualTo(bean); } } ================================================ FILE: src/test/java/org/joda/beans/ser/json/TestJsonInput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.offset; import java.io.IOException; import java.io.StringReader; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test {@link JsonInput}. */ class TestJsonInput { //----------------------------------------------------------------------- static Object[][] data_string() { return new Object[][] { {"", ""}, {"normal text", "normal text"}, {"\\\"", "\""}, {"\\\\", "\\"}, {"a\\\\b", "a\\b"}, {"a\\\"b", "a\"b"}, {"a\\\\\\\"b", "a\\\"b"}, {"a\\nb", "a\nb"}, {"a\\fb", "a\fb"}, {"a\\/b", "a/b"}, {"foo\\r\\nbar", "foo\r\nbar"}, {"foo\\tbar", "foo\tbar"}, {"foo\\u2028bar\\u2029\u2030", "foo\u2028bar\u2029\u2030"}, {"foo\\u0000bar", "foo\u0000bar"}, {"foo\\u001bbar", "foo\u001bbar"}, {"\\u0001\\b\\u000f\\u0010\\u001f", "\u0001\u0008\u000f\u0010\u001f"}, {"\\u000a\\u000A\\u0010\\u001e\\u001E", "\n\n\u0010\u001e\u001e"}, }; } @ParameterizedTest @MethodSource("data_string") void test_parseString(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + '"')); assertThat(input.parseString()).isEqualTo(expected); } @ParameterizedTest @MethodSource("data_string") void test_parseString_endOfFile(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text)); assertThatIllegalArgumentException() .isThrownBy(() -> input.parseString()); } @ParameterizedTest @MethodSource("data_string") void test_acceptString(String text, String expected) throws IOException { var input = new JsonInput(new StringReader('"' + text + '"')); assertThat(input.acceptString()).isEqualTo(expected); } @ParameterizedTest @MethodSource("data_string") void test_acceptString_whitespace(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(" \t\r\n \"" + text + '"')); assertThat(input.acceptString()).isEqualTo(expected); } @ParameterizedTest @MethodSource("data_string") void test_acceptString_pushback(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + '"')); input.pushBack('"'); assertThat(input.acceptString()).isEqualTo(expected); } static Object[][] data_stringBad() { return new Object[][] { {"\\x"}, {"\\u1"}, {"\\u01"}, {"\\u001"}, {"\\u000g"}, {"\\urubbish"}, }; } @ParameterizedTest @MethodSource("data_stringBad") void test_parseString_bad(String text) throws IOException { var input = new JsonInput(new StringReader(text + '"')); assertThatIllegalArgumentException() .isThrownBy(() -> input.parseString()); } @ParameterizedTest @MethodSource("data_stringBad") void test_acceptString_bad(String text) throws IOException { var input = new JsonInput(new StringReader('"' + text + '"')); assertThatIllegalArgumentException() .isThrownBy(() -> input.acceptString()); } @ParameterizedTest @MethodSource("data_stringBad") void test_acceptString_bad_whitespace(String text) throws IOException { var input = new JsonInput(new StringReader(" \t\r\n \"" + text + '"')); assertThatIllegalArgumentException() .isThrownBy(() -> input.acceptString()); } //----------------------------------------------------------------------- @ParameterizedTest @MethodSource("data_string") void test_parseObjectKey(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + "\":")); assertThat(input.parseObjectKey()).isEqualTo(expected); } @ParameterizedTest @MethodSource("data_string") void test_parseObjectKey_whitspace(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + "\" \t\n\r:")); assertThat(input.parseObjectKey()).isEqualTo(expected); } //----------------------------------------------------------------------- @ParameterizedTest @MethodSource("data_string") void test_acceptObjectKey(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + "\":")); assertThat(input.acceptObjectKey(JsonEvent.STRING)).isEqualTo(expected); } @ParameterizedTest @MethodSource("data_string") void test_acceptObjectKey_whitspace(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + "\" \t\n\r:")); assertThat(input.acceptObjectKey(JsonEvent.STRING)).isEqualTo(expected); } @ParameterizedTest @MethodSource("data_string") void test_acceptObjectKey_notString(String text, String expected) throws IOException { var input = new JsonInput(new StringReader(text + "\":")); assertThatIllegalArgumentException() .isThrownBy(() -> input.acceptObjectKey(JsonEvent.OBJECT)); } @Test void test_acceptObjectKey_pushBack() throws IOException { var input = new JsonInput(new StringReader(":")); input.pushBackObjectKey("key"); assertThat(input.acceptObjectKey(JsonEvent.STRING)).isEqualTo("key"); } //----------------------------------------------------------------------- static Object[][] data_numberIntegral() { return new Object[][] { {"0", 0L}, {"1", 1L}, {"9", 9L}, {"10", 10L}, {"19", 19L}, {"123456789", 123456789L}, {"1234567890123456789", 1234567890123456789L}, {"-0", 0L}, {"-1", -1L}, {"-9", -9L}, {"-10", -10L}, {"-19", -19L}, {"-123456789", -123456789L}, {"-1234567890123456789", -1234567890123456789L}, }; } @ParameterizedTest @MethodSource("data_numberIntegral") void test_parseNumberIntegral(String text, long expected) throws IOException { var input = new JsonInput(new StringReader(text + '}')); assertThat(input.readEvent()).isEqualTo(JsonEvent.NUMBER_INTEGRAL); assertThat(input.parseNumberIntegral()).isEqualTo(expected); assertThat(input.readEvent()).isEqualTo(JsonEvent.OBJECT_END); } @ParameterizedTest @MethodSource("data_numberIntegral") void test_parseNumberIntegral_endOfFile(String text, long expected) throws IOException { var input = new JsonInput(new StringReader(text)); assertThatIllegalArgumentException() .isThrownBy(() -> input.readEvent()); } //----------------------------------------------------------------------- static Object[][] data_numberFloating() { return new Object[][] { {"0.0", 0d}, {"1.0", 1d}, {"9.0", 9d}, {"10.0", 10d}, {"19.0", 19d}, {"123456789.0", 123456789d}, {"1234567890123456789.0", 1234567890123456789d}, {"-0.0", 0d}, {"-1.0", -1d}, {"-9.0", -9d}, {"-10.0", -10d}, {"-19.0", -19d}, {"-123456789.0", -123456789d}, {"-1234567890123456789.0", -1234567890123456789d}, {"0.0001", 0.0001d}, {"1.12345678", 1.12345678d}, {"9.0e2", 9.0e2d}, {"9e2", 9e2d}, {"123.456e20", 123.456e20d}, {"123.456e+20", 123.456e+20d}, {"123.456e-20", 123.456e-20d}, {"9.0E2", 9.0e2d}, {"9E2", 9e2d}, {"123.456E20", 123.456e20d}, {"123.456E+20", 123.456e+20d}, {"123.456E-20", 123.456e-20d}, }; } @ParameterizedTest @MethodSource("data_numberFloating") void test_parseNumberFloating(String text, double expected) throws IOException { var input = new JsonInput(new StringReader(text + '}')); assertThat(input.readEvent()).isEqualTo(JsonEvent.NUMBER_FLOATING); assertThat(input.parseNumberFloating()).isCloseTo(expected, offset(0.00001d)); assertThat(input.readEvent()).isEqualTo(JsonEvent.OBJECT_END); } @ParameterizedTest @MethodSource("data_numberFloating") void test_parseNumberFloating_endOfFile(String text, double expected) throws IOException { var input = new JsonInput(new StringReader(text)); assertThatIllegalArgumentException() .isThrownBy(() -> input.readEvent()); } //----------------------------------------------------------------------- static Object[][] data_numberBad() { return new Object[][] { {"-"}, {"x"}, {"e"}, {"E"}, {"1e"}, {"2E"}, {"1+"}, {"1-"}, {"1."}, {"00"}, {"001"}, {"00.0"}, {"1.1e3E4"}, }; } @ParameterizedTest @MethodSource("data_numberBad") void test_parseNumberFloating_bad(String text) throws IOException { var input = new JsonInput(new StringReader(text + '}')); assertThatIllegalArgumentException() .isThrownBy(() -> input.readEvent()); } //----------------------------------------------------------------------- static Object[][] data_event() { return new Object[][] { {"null", JsonEvent.NULL}, {"true", JsonEvent.TRUE}, {"false", JsonEvent.FALSE}, {"{", JsonEvent.OBJECT}, {"}", JsonEvent.OBJECT_END}, {"[", JsonEvent.ARRAY}, {"]", JsonEvent.ARRAY_END}, {"\"", JsonEvent.STRING}, {"-1}", JsonEvent.NUMBER_INTEGRAL}, {"1}", JsonEvent.NUMBER_INTEGRAL}, {"1.0}", JsonEvent.NUMBER_FLOATING}, {"-1.2}", JsonEvent.NUMBER_FLOATING}, {":", JsonEvent.COLON}, {",", JsonEvent.COMMA}, }; } @ParameterizedTest @MethodSource("data_event") void test_readEvent(String text, JsonEvent expected) throws IOException { var input = new JsonInput(new StringReader(text)); assertThat(input.readEvent()).isEqualTo(expected); } static Object[][] data_eventBad() { return new Object[][] { {"nul"}, {"nulx"}, {"nx"}, {"tru"}, {"trux"}, {"tx"}, {"fals"}, {"fx"}, {"x"}, }; } @ParameterizedTest @MethodSource("data_eventBad") void test_readEvent_bad(String text) throws IOException { var input = new JsonInput(new StringReader(text)); assertThatIllegalArgumentException() .isThrownBy(() -> input.readEvent()); } //----------------------------------------------------------------------- static Object[][] data_skip() { return new Object[][] { {"null"}, {"true"}, {"false"}, {"\"\""}, {"\"text\""}, {"-1"}, {"1"}, {"1.0"}, {"-1.2"}, {"{}"}, {"{\"a\":2}"}, {"{\"a\":2,\"b\":{\"aa\":[1,2,3]}}"}, {"[]"}, {"[1,2,3]"}, {"[1,[\"\"],{\"a\":2}]"}, }; } @ParameterizedTest @MethodSource("data_skip") void test_skip(String text) throws IOException { var input = new JsonInput(new StringReader(text + ',')); input.skipData(); assertThat(input.readEvent()).isEqualTo(JsonEvent.COMMA); } @Test void test_skip_bad() throws IOException { var input = new JsonInput(new StringReader(",")); assertThatIllegalArgumentException() .isThrownBy(() -> input.skipData()); } } ================================================ FILE: src/test/java/org/joda/beans/ser/json/TestJsonOutput.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test {@link JsonOutput}. */ class TestJsonOutput { private StringBuilder buf; private JsonOutput outputCompact; private JsonOutput outputPretty; @BeforeEach void setUp() { buf = new StringBuilder(); outputCompact = new JsonOutput(buf); outputPretty = new JsonOutput(buf, JodaBeanJsonNumberFormat.STRING, " ", "\n"); } //----------------------------------------------------------------------- static Object[][] data_string() { return new Object[][] { {"", ""}, {"\"", "\\\""}, {"\\", "\\\\"}, {"a\\b", "a\\\\b"}, {"a\"b", "a\\\"b"}, {"a\\\"b", "a\\\\\\\"b"}, {"a\nb", "a\\nb"}, {"foo\r\nbar", "foo\\r\\nbar"}, {"foo\tbar", "foo\\tbar"}, {"foo\u2028bar\u2029\u2030", "foo\\u2028bar\\u2029\u2030"}, {"foo\u0000bar", "foo\\u0000bar"}, {"foo\u001bbar", "foo\\u001bbar"}, {"\u0001\u0008\u000f\u0010\u001f", "\\u0001\\b\\u000f\\u0010\\u001f"}, }; } @ParameterizedTest @MethodSource("data_string") void test_writeString(String input, String expected) throws IOException { outputCompact.writeString(input); assertThat(buf.toString()).isEqualTo('"' + expected + '"'); } //----------------------------------------------------------------------- static Object[][] data_int() { return new Object[][] { {0, "0"}, {1, "1"}, {2, "2"}, {1234567, "1234567"}, {-1, "-1"}, {-1234567, "-1234567"}, }; } @ParameterizedTest @MethodSource("data_int") void test_writeInt(int input, String expected) throws IOException { outputCompact.writeInt(input); assertThat(buf.toString()).isEqualTo(expected); } static Object[][] data_long() { return new Object[][] { {0, "0"}, {1, "1"}, {2, "2"}, {1234567, "1234567"}, {-1, "-1"}, {-1234567, "-1234567"}, }; } @ParameterizedTest @MethodSource("data_long") void test_writeLong(long input, String expected) throws IOException { outputCompact.writeLong(input); assertThat(buf.toString()).isEqualTo(expected); } static Object[][] data_double() { return new Object[][] { {0d, "0.0"}, {1d, "1.0"}, {2d, "2.0"}, {1234567d, "1234567.0"}, {-1d, "-1.0"}, {-1234567d, "-1234567.0"}, {0.000001d, "1.0E-6"}, {0.1234d, "0.1234"}, {Double.NaN, "\"NaN\""}, {Double.POSITIVE_INFINITY, "\"Infinity\""}, {Double.NEGATIVE_INFINITY, "\"-Infinity\""}, }; } @ParameterizedTest @MethodSource("data_double") void test_writeDouble(double input, String expected) throws IOException { outputCompact.writeDouble(input); assertThat(buf.toString()).isEqualTo(expected); } static Object[][] data_float() { return new Object[][] { {0f, "0.0"}, {1f, "1.0"}, {2f, "2.0"}, {1234567f, "1234567.0"}, {-1f, "-1.0"}, {-1234567f, "-1234567.0"}, {0.000001f, "1.0E-6"}, {0.1234f, "0.1234"}, {Float.NaN, "\"NaN\""}, {Float.POSITIVE_INFINITY, "\"Infinity\""}, {Float.NEGATIVE_INFINITY, "\"-Infinity\""}, }; } @ParameterizedTest @MethodSource("data_float") void test_writeFloat(float input, String expected) throws IOException { outputCompact.writeFloat(input); assertThat(buf.toString()).isEqualTo(expected); } //----------------------------------------------------------------------- @Test void test_writeNull() throws IOException { outputCompact.writeNull(); assertThat(buf.toString()).isEqualTo("null"); } @Test void test_writeBoolean_true() throws IOException { outputCompact.writeBoolean(true); assertThat(buf.toString()).isEqualTo("true"); } @Test void test_writeBoolean_false() throws IOException { outputCompact.writeBoolean(false); assertThat(buf.toString()).isEqualTo("false"); } //----------------------------------------------------------------------- @Test void test_write_array0() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[]"); } @Test void test_write_array1() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("a"); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\"]"); } @Test void test_write_array2() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("a"); outputCompact.writeArrayItemStart(); outputCompact.writeString("b"); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\",\"b\"]"); } @Test void test_write_array3() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("a"); outputCompact.writeArrayItemStart(); outputCompact.writeString("b"); outputCompact.writeArrayItemStart(); outputCompact.writeString("c"); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\",\"b\",\"c\"]"); } @Test void test_write_arrayDeep0() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("a"); outputCompact.writeArrayItemStart(); outputCompact.writeArrayStart(); outputCompact.writeArrayEnd(); outputCompact.writeArrayItemStart(); outputCompact.writeString("c"); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\",[],\"c\"]"); } @Test void test_write_arrayDeep1() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("a"); outputCompact.writeArrayItemStart(); outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("b1"); outputCompact.writeArrayEnd(); outputCompact.writeArrayItemStart(); outputCompact.writeString("c"); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\",[\"b1\"],\"c\"]"); } @Test void test_write_arrayDeep2() throws IOException { outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("a"); outputCompact.writeArrayItemStart(); outputCompact.writeArrayStart(); outputCompact.writeArrayItemStart(); outputCompact.writeString("b1"); outputCompact.writeArrayItemStart(); outputCompact.writeString("b2"); outputCompact.writeArrayEnd(); outputCompact.writeArrayItemStart(); outputCompact.writeString("c"); outputCompact.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\",[\"b1\",\"b2\"],\"c\"]"); } //----------------------------------------------------------------------- @Test void test_write_object0() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{}"); } @Test void test_write_object1() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectKey("a"); outputCompact.writeString("aa"); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\"a\":\"aa\"}"); } @Test void test_write_object2() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectKey("a"); outputCompact.writeString("aa"); outputCompact.writeObjectKey("b"); outputCompact.writeString("bb"); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\"a\":\"aa\",\"b\":\"bb\"}"); } @Test void test_write_object3() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectKeyValue("a", "aa"); outputCompact.writeObjectKeyValue("b", "bb"); outputCompact.writeObjectKeyValue("c", "cc"); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\"a\":\"aa\",\"b\":\"bb\",\"c\":\"cc\"}"); } @Test void test_write_objectDeep0() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectKeyValue("a", "aa"); outputCompact.writeObjectKey("b"); outputCompact.writeObjectStart(); outputCompact.writeObjectEnd(); outputCompact.writeObjectKeyValue("c", "cc"); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\"a\":\"aa\",\"b\":{},\"c\":\"cc\"}"); } @Test void test_write_objectDeep1() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectKeyValue("a", "aa"); outputCompact.writeObjectKey("b"); outputCompact.writeObjectStart(); outputCompact.writeObjectKeyValue("bb", "bbb"); outputCompact.writeObjectEnd(); outputCompact.writeObjectKeyValue("c", "cc"); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\"a\":\"aa\",\"b\":{\"bb\":\"bbb\"},\"c\":\"cc\"}"); } @Test void test_write_objectDeep2() throws IOException { outputCompact.writeObjectStart(); outputCompact.writeObjectKeyValue("a", "aa"); outputCompact.writeObjectKey("b"); outputCompact.writeObjectStart(); outputCompact.writeObjectKeyValue("bb1", "bbb1"); outputCompact.writeObjectKeyValue("bb2", "bbb2"); outputCompact.writeObjectEnd(); outputCompact.writeObjectKeyValue("c", "cc"); outputCompact.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\"a\":\"aa\",\"b\":{\"bb1\":\"bbb1\",\"bb2\":\"bbb2\"},\"c\":\"cc\"}"); } //----------------------------------------------------------------------- @Test void test_write_array0_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[]"); } @Test void test_write_array1_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("a"); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\"]"); } @Test void test_write_array2_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("a"); outputPretty.writeArrayItemStart(); outputPretty.writeString("b"); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\", \"b\"]"); } @Test void test_write_array3_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("a"); outputPretty.writeArrayItemStart(); outputPretty.writeString("b"); outputPretty.writeArrayItemStart(); outputPretty.writeString("c"); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\", \"b\", \"c\"]"); } @Test void test_write_arrayDeep0_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("a"); outputPretty.writeArrayItemStart(); outputPretty.writeArrayStart(); outputPretty.writeArrayEnd(); outputPretty.writeArrayItemStart(); outputPretty.writeString("c"); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\", [], \"c\"]"); } @Test void test_write_arrayDeep1_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("a"); outputPretty.writeArrayItemStart(); outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("b1"); outputPretty.writeArrayEnd(); outputPretty.writeArrayItemStart(); outputPretty.writeString("c"); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\", [\"b1\"], \"c\"]"); } @Test void test_write_arrayDeep2_pretty() throws IOException { outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("a"); outputPretty.writeArrayItemStart(); outputPretty.writeArrayStart(); outputPretty.writeArrayItemStart(); outputPretty.writeString("b1"); outputPretty.writeArrayItemStart(); outputPretty.writeString("b2"); outputPretty.writeArrayEnd(); outputPretty.writeArrayItemStart(); outputPretty.writeString("c"); outputPretty.writeArrayEnd(); assertThat(buf.toString()).isEqualTo("[\"a\", [\"b1\", \"b2\"], \"c\"]"); } //----------------------------------------------------------------------- @Test void test_write_object0_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{}"); } @Test void test_write_object1_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectKey("a"); outputPretty.writeString("aa"); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\n \"a\": \"aa\"\n}"); } @Test void test_write_object2_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectKey("a"); outputPretty.writeString("aa"); outputPretty.writeObjectKey("b"); outputPretty.writeString("bb"); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\n \"a\": \"aa\",\n \"b\": \"bb\"\n}"); } @Test void test_write_object3_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectKeyValue("a", "aa"); outputPretty.writeObjectKeyValue("b", "bb"); outputPretty.writeObjectKeyValue("c", "cc"); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\n \"a\": \"aa\",\n \"b\": \"bb\",\n \"c\": \"cc\"\n}"); } @Test void test_write_objectDeep0_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectKeyValue("a", "aa"); outputPretty.writeObjectKey("b"); outputPretty.writeObjectStart(); outputPretty.writeObjectEnd(); outputPretty.writeObjectKeyValue("c", "cc"); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\n \"a\": \"aa\",\n \"b\": {},\n \"c\": \"cc\"\n}"); } @Test void test_write_objectDeep1_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectKeyValue("a", "aa"); outputPretty.writeObjectKey("b"); outputPretty.writeObjectStart(); outputPretty.writeObjectKeyValue("bb", "bbb"); outputPretty.writeObjectEnd(); outputPretty.writeObjectKeyValue("c", "cc"); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo("{\n \"a\": \"aa\",\n \"b\": {\n \"bb\": \"bbb\"\n },\n \"c\": \"cc\"\n}"); } @Test void test_write_objectDeep2_pretty() throws IOException { outputPretty.writeObjectStart(); outputPretty.writeObjectKeyValue("a", "aa"); outputPretty.writeObjectKey("b"); outputPretty.writeObjectStart(); outputPretty.writeObjectKeyValue("bb1", "bbb1"); outputPretty.writeObjectKeyValue("bb2", "bbb2"); outputPretty.writeObjectEnd(); outputPretty.writeObjectKeyValue("c", "cc"); outputPretty.writeObjectEnd(); assertThat(buf.toString()).isEqualTo(""" { "a": "aa", "b": { "bb1": "bbb1", "bb2": "bbb2" }, "c": "cc" }\ """); } } ================================================ FILE: src/test/java/org/joda/beans/ser/json/TestJsonPerformance.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import java.io.IOException; import java.time.Duration; import org.joda.beans.sample.Address; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTestHelper; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import com.google.common.base.Stopwatch; /** * Test bean round-trip using JSON. */ @Disabled("Performance test - run manually when needed") class TestJsonPerformance { private static final int REPEAT_OUTER = 20; private static final int REPEAT_INNER = 5000; @Test void testPerformance() throws IOException { var address = SerTestHelper.testAddress(); invokeNew(address); invokeOld(address); invokeNew(address); invokeOld(address); invokeNew(address); invokeOld(address); System.out.println("---"); invokeNew(address); invokeOld(address); } private void invokeNew(Address address) { String json; var total = Duration.ZERO; for (int i = 0; i < REPEAT_OUTER; i++) { Stopwatch watch = Stopwatch.createStarted(); for (int j = 0; j < REPEAT_INNER; j++) { json = new JodaBeanJsonWriter(JodaBeanSer.PRETTY).write(address); if (json.length() < 1000) { System.out.println(); } } watch.stop(); total = total.plus(watch.elapsed()); } System.out.println("NEW-AVG-J: " + ((total.dividedBy(REPEAT_OUTER).toNanos() / 1000) / 1000d) + " ms"); } private void invokeOld(Address address) { String json; var total = Duration.ZERO; for (int i = 0; i < REPEAT_OUTER; i++) { Stopwatch watch = Stopwatch.createStarted(); for (int j = 0; j < REPEAT_INNER; j++) { json = new JodaBeanSimpleJsonWriter(JodaBeanSer.PRETTY).write(address); if (json.length() < 1000) { System.out.println(); } } watch.stop(); total = total.plus(watch.elapsed()); } System.out.println("OLD-AVG-J: " + ((total.dividedBy(REPEAT_OUTER).toNanos() / 1000) / 1000d) + " ms"); } } ================================================ FILE: src/test/java/org/joda/beans/ser/json/TestSerializeJson.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.offset; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.nio.charset.StandardCharsets; import org.joda.beans.Bean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmArrays; import org.joda.beans.sample.ImmDoubleFloat; import org.joda.beans.sample.ImmEmpty; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmKey; import org.joda.beans.sample.ImmMappedKey; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.JodaConvertBean; import org.joda.beans.sample.JodaConvertWrapper; import org.joda.beans.sample.Person; import org.joda.beans.sample.PrimitiveBean; import org.joda.beans.sample.SimplePerson; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerDeserializers; import org.joda.beans.ser.SerTestHelper; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import com.google.common.collect.ImmutableMap; import com.google.common.io.Resources; /** * Test property roundtrip using JSON. */ class TestSerializeJson { @Test void test_writeAddress() throws IOException { var bean = SerTestHelper.testAddress(); var json = JodaBeanSer.PRETTY.jsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/Address2.json"); var parsed = (Address) JodaBeanSer.PRETTY.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmAddress() throws IOException { var bean = SerTestHelper.testImmAddress(false); var json = JodaBeanSer.PRETTY.jsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/ImmAddress2.json"); var parsed = (ImmAddress) JodaBeanSer.PRETTY.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); var oldParsed = loadAndParse("/org/joda/beans/ser/ImmAddress1.json", ImmAddress.class); BeanAssert.assertBeanEquals(bean, oldParsed); } @Test void test_writeImmOptional() throws IOException { var bean = SerTestHelper.testImmOptional(); var json = JodaBeanSer.PRETTY.withIncludeDerived(true).jsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/ImmOptional2.json"); var parsed = (ImmOptional) JodaBeanSer.PRETTY.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmArrays() throws IOException { var bean = ImmArrays.of( new int[] {1, 3, 2}, new long[] {1, 4, 3}, new double[] {1.1, 2.2, 3.3}, new boolean[] {true, false}, new int[][] {{1, 2}, {2}, {}}, new boolean[][] {{true, false}, {false}, {}}); var json = JodaBeanSer.PRETTY.jsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/ImmArrays2.json"); var parsed = JodaBeanSer.PRETTY.simpleJsonReader().read(json, ImmArrays.class); BeanAssert.assertBeanEquals(bean, parsed); var oldParsed = loadAndParse("/org/joda/beans/ser/ImmArrays1.json", ImmArrays.class); BeanAssert.assertBeanEquals(bean, oldParsed); } @Test void test_writeCollections() throws IOException { var bean = SerTestHelper.testCollections(true); var json = JodaBeanSer.PRETTY.jsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/Collections2.json"); var parsed = JodaBeanSer.PRETTY.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); var oldParsed = loadAndParse("/org/joda/beans/ser/Collections1.json", ImmGuava.class); BeanAssert.assertBeanEquals(bean, oldParsed); } @Test void test_writeJodaConvertInterface() { var bean = SerTestHelper.testGenericInterfaces(); var json = JodaBeanSer.PRETTY.jsonWriter().write(bean); // System.out.println(json); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } private void assertEqualsSerialization(String json, String expectedResource) throws IOException { var url = TestSerializeJson.class.getResource(expectedResource); var expected = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); assertThat(json.trim().replace(System.lineSeparator(), "\n")) .isEqualTo(expected.trim().replace(System.lineSeparator(), "\n")); } private T loadAndParse(String expectedResource, Class type) throws IOException { var url = TestSerializeJson.class.getResource(expectedResource); var text = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); return JodaBeanSer.PRETTY.simpleJsonReader().read(text, type); } //----------------------------------------------------------------------- @Test void test_readWriteBeanEmptyChild_pretty() { var bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", ImmEmpty.builder().build()); var json = JodaBeanSer.PRETTY.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\n \"@bean\": \"org.joda.beans.impl.flexi.FlexiBean\",\n" + " \"element\": \"Test\",\n \"child\": {\n \"@bean\": \"org.joda.beans.sample.ImmEmpty\"\n }\n}\n"); var parsed = JodaBeanSer.PRETTY.jsonReader().read(json, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWriteBeanEmptyChild_compact() { var bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", ImmEmpty.builder().build()); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\"," + "\"element\":\"Test\",\"child\":{\"@bean\":\"org.joda.beans.sample.ImmEmpty\"}}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_primitiveTypeChanged() throws IOException { var json = "{\"a\":6,\"b\":5}"; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, ImmDoubleFloat.class); assertThat(parsed.getA()).isCloseTo(6, offset(1e-10)); assertThat(parsed.getB()).isCloseTo(5, offset(1e-10)); } @Test void test_readWriteJodaConvertWrapper() { var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); var json = JodaBeanSer.COMPACT.jsonWriter().write(wrapper); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.sample.JodaConvertWrapper\",\"bean\":\"Hello:9\",\"description\":\"Weird\"}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_readWriteJodaConvertBean() { var bean = new JodaConvertBean("Hello:9"); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo("" + "{\"@bean\":\"org.joda.beans.sample.JodaConvertBean\",\"base\":\"Hello\",\"extra\":9}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_readWrite_objectArrayAsObject() { var bean = new FlexiBean(); bean.set("data", new Object[] {"1", 2, 3L, 4d, 5f}); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@meta":"Object[]",\ "value":["1",2,{"@type":"Long","value":3},4.0,{"@type":"Float","value":5.0}]}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_stringArrayAsObject() { var bean = new FlexiBean(); bean.set("data", new String[] {"1", "2"}); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@meta":"String[]","value":["1","2"]}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_numberArrayAsObject() { var bean = new FlexiBean(); bean.set("data", new Number[] {1, 2.3, 4L}); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@meta":"java.lang.Number[]","value":[1,2.3,{"@type":"Long","value":4}]}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_longArrayAsObject() { var bean = new FlexiBean(); bean.set("data", new long[] {1L, 2L, 3L}); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@meta":"long[]","value":[1,2,3]}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_intArrayAsObject() { var bean = new FlexiBean(); bean.set("data", new int[] {1, 2, 3}); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@meta":"int[]","value":[1,2,3]}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_readWrite_booleanObject_true() { var bean = new FlexiBean(); bean.set("data", Boolean.TRUE); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":true}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_boolean_false() { var bean = new FlexiBean(); bean.set("data", Boolean.FALSE); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":false}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(new StringReader(json)); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_longObject() { var bean = new FlexiBean(); bean.set("data", (long) 6); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":{\"@type\":\"Long\",\"value\":6}}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_shortObject() { var bean = new FlexiBean(); bean.set("data", (short) 6); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":{\"@type\":\"Short\",\"value\":6}}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_byteObject() { var bean = new FlexiBean(); bean.set("data", (byte) 6); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":{\"@type\":\"Byte\",\"value\":6}}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_floatObject() { var bean = new FlexiBean(); bean.set("data", (float) 6); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":{\"@type\":\"Float\",\"value\":6.0}}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_floatObject_NaN() { var bean = new FlexiBean(); bean.set("data", Float.NaN); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo( "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"data\":{\"@type\":\"Float\",\"value\":\"NaN\"}}"); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_float_NaN_asNull() { var bean = new PrimitiveBean(); bean.setValueFloat(Float.NaN); var json = "{\"@bean\":\"org.joda.beans.sample.PrimitiveBean\",\"valueFloat\":null}"; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_float_fromInteger() { var bean = new PrimitiveBean(); bean.setValueFloat(6f); var json = "{\"@bean\":\"org.joda.beans.sample.PrimitiveBean\",\"valueFloat\":6}"; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_float_fromIntegerTooBig() { var json = "{\"@bean\":\"org.joda.beans.sample.PrimitiveBean\",\"valueFloat\":123456789123456789}"; assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader().read(json)); } //------------------------------------------------------------------------- @Test void test_readWrite_doubleObject() { var bean = new FlexiBean(); bean.set("data", (double) 6); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":6.0}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_doubleObject_NaN() { var bean = new FlexiBean(); bean.set("data", Double.NaN); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@type":"Double","value":"NaN"}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_doubleObject_PositiveInfinity() { var bean = new FlexiBean(); bean.set("data", Double.POSITIVE_INFINITY); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@type":"Double","value":"Infinity"}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_doubleObject_NegativeInfinity() { var bean = new FlexiBean(); bean.set("data", Double.NEGATIVE_INFINITY); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@type":"Double","value":"-Infinity"}}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NaN() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":"NaN","valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NaN_null() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.NAN_AS_NULL).jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":null,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NaN_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.LITERAL).jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":NaN,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_PositiveInfinity_string() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.POSITIVE_INFINITY); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":"Infinity","valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_PositiveInfinity_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.POSITIVE_INFINITY); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.LITERAL).jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":Infinity,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_double_PositiveInfinity_string() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.POSITIVE_INFINITY); var json = """ {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":+Infinity,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NegativeInfinity_string() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NEGATIVE_INFINITY); var json = JodaBeanSer.COMPACT.jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":"-Infinity","valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NegativeInfinity_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NEGATIVE_INFINITY); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.LITERAL).jsonWriter().write(bean); assertThat(json).isEqualTo(""" {"@bean":"org.joda.beans.sample.PrimitiveBean","valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":-Infinity,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_doubleObject_alternateFormat() { var bean = new FlexiBean(); bean.set("data", (double) 6); var json = """ {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@type":"Double","value":6.0}}"""; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_doubleObject_integer_flexiWithTypeAnnotation() { var bean = new FlexiBean(); bean.set("data", Double.valueOf(6)); var json = """ {"@bean":"org.joda.beans.impl.flexi.FlexiBean","data":{"@type":"Double","value":6}}"""; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_double_NaN_asNull_alternateFormat() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = """ {"@bean":"org.joda.beans.sample.PrimitiveBean","valueDouble":null}"""; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_double_fromInteger() { var bean = new PrimitiveBean(); bean.setValueDouble(6d); var json = """ {"@bean":"org.joda.beans.sample.PrimitiveBean","valueDouble":6}"""; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_double_fromIntegerTooBig() { var json = """ {"@bean":"org.joda.beans.sample.PrimitiveBean","data":{"@type":"Double","value":123456789123456789}}"""; assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader().read(json)); } //----------------------------------------------------------------------- @Test void test_read_nonStandard_JodaConvertWrapper_expanded() { var json = "{\"@bean\":\"org.joda.beans.sample.JodaConvertWrapper\"," + "\"bean\":{\"base\":\"Hello\",\"extra\":9},\"description\":\"Weird\"}"; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_read_nonStandard_JodaConvertBean_flattened() { var json = "{\"@type\":\"org.joda.beans.sample.JodaConvertBean\",\"value\":\"Hello:9\"}"; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json); var bean = new JodaConvertBean("Hello:9"); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWriteInterfaceKeyMap() { var key1 = ImmKey.builder().name("Alpha").build(); var person1 = ImmPerson.builder().forename("Bob").surname("Builder").build(); var key2 = ImmKey.builder().name("Beta").build(); var person2 = ImmPerson.builder().forename("Dana").surname("Dash").build(); var mapped = ImmMappedKey.builder().data(ImmutableMap.of(key1, person1, key2, person2)).build(); var json = JodaBeanSer.PRETTY.jsonWriter().write(mapped); var bean = (ImmMappedKey) JodaBeanSer.PRETTY.jsonReader().read(json); BeanAssert.assertBeanEquals(bean, mapped); } @Test void test_read_badTypeInMap() { var json = "{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\",\"element\":{" + "\"@meta\": \"Map\"," + "\"value\": [[\"work\", {\"@type\": \"com.foo.UnknownEnum\",\"value\": \"BIGWIG\"}]]}}"; var parsed = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT).jsonReader().read(json, FlexiBean.class); var bean = new FlexiBean(); bean.set("element", ImmutableMap.of("work", "BIGWIG")); // converted to a string BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_ignoreProperty() { var xml = "{\"name\":\"foo\",\"wibble\":\"ignored\"}"; var parsed = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT).jsonReader().read(xml, ImmKey.class); var bean = ImmKey.builder().name("foo").build(); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_noTypeAttributeAtRoot() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader().read("{}")); } @Test void test_read_noTypeAttributeAtRootButTypeSpecified() { var parsed = JodaBeanSer.COMPACT.jsonReader().read("{}", FlexiBean.class); BeanAssert.assertBeanEquals(new FlexiBean(), parsed); } @Test void test_read_rootTypeAttributeNotBean() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader().read("{\"@bean\":\"java.lang.Integer\"}", Bean.class)); } @Test void test_read_rootTypeInvalid() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader() .read("{\"@bean\":\"org.joda.beans.impl.flexi.FlexiBean\"}", SimplePerson.class)); } @Test void test_read_rootTypeArgumentInvalid() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader().read("{}", Integer.class)); } @Test void test_write_nullKeyInMap() { var address = new Address(); var bean = new Person(); bean.getOtherAddressMap().put(null, address); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonWriter().write(bean)); } //----------------------------------------------------------------------- static Object[][] data_badFormat() { return new Object[][] { {"{,}"}, {"{1,2}"}, {"{\"a\",6}"}, {"{\"a\":[}}"}, {"{\"a\":{\"@type\":\"Integer\",\"notvalue\":6}}"}, {"{\"a\":{\"@type\":\"Integer\",\"value\":[]}}"}, {"{\"a\":{\"@type\":\"Integer\",\"value\":" + (((long) Integer.MAX_VALUE) + 1) + "}}"}, {"{\"a\":{\"@type\":\"Integer\",\"value\":" + (((long) Integer.MIN_VALUE) - 1) + "}}"}, {"{\"a\":{\"@type\":\"Short\",\"value\":" + ((Short.MAX_VALUE) + 1) + "}}"}, {"{\"a\":{\"@type\":\"Short\",\"value\":" + ((Short.MIN_VALUE) - 1) + "}}"}, {"{\"a\":{\"@type\":\"Byte\",\"value\":128}}"}, {"{\"a\":{\"@type\":\"Byte\",\"value\":-129}}"}, {"{\"a\":{\"@meta\":\"List\",\"notvalue\":[]}}"}, {"{\"a\":{\"@meta\":\"List\",\"value\":{}}}"}, {"{\"a\":{\"@meta\":\"Map\",\"value\":6}}"}, }; } @ParameterizedTest @MethodSource("data_badFormat") void test_badFormat(String text) throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.jsonReader().read(text, FlexiBean.class)); } //----------------------------------------------------------------------- @Test void test_writer_nullSettings() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonWriter(null)); } @Test void test_writer_write1_nullBean() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonWriter(JodaBeanSer.PRETTY).write(null)); } @Test void test_writer_write2_nullBean() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonWriter(JodaBeanSer.PRETTY).write(null, new StringBuilder())); } @Test void test_writer_write2_nullAppendable() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonWriter(JodaBeanSer.PRETTY).write(new FlexiBean(), null)); } //----------------------------------------------------------------------- @Test void test_reader_nullSettings() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(null)); } @Test void test_reader_readReader_null() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(JodaBeanSer.PRETTY).read((Reader) null)); } @Test void test_reader_readString_null() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(JodaBeanSer.PRETTY).read((String) null)); } @Test void test_reader_readReaderType_nullReader() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(JodaBeanSer.PRETTY).read((Reader) null, Bean.class)); } @Test void test_reader_readReaderType_nullType() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(JodaBeanSer.PRETTY).read(new StringReader(""), null)); } @Test void test_reader_readStringType_nullString() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(JodaBeanSer.PRETTY).read((String) null, Bean.class)); } @Test void test_reader_readStringType_nullType() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanJsonReader(JodaBeanSer.PRETTY).read("", null)); } } ================================================ FILE: src/test/java/org/joda/beans/ser/json/TestSerializeJsonSimple.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.json; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.offset; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.util.HashMap; import org.joda.beans.Bean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmArrays; import org.joda.beans.sample.ImmDoubleFloat; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.Person; import org.joda.beans.sample.PrimitiveBean; import org.joda.beans.sample.SimpleJson; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerDeserializers; import org.joda.beans.ser.SerTestHelper; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import com.google.common.io.Resources; /** * Test property roundtrip using JSON. */ class TestSerializeJsonSimple { @Test void test_writeSimpleJson() throws IOException { var bean = SerTestHelper.testSimpleJson(); var json = JodaBeanSer.PRETTY.withJsonNumberFormat(JodaBeanJsonNumberFormat.COMPATIBLE_V2).simpleJsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/SimpleJson2.simplejson"); var parsed = JodaBeanSer.PRETTY.simpleJsonReader().read(json, SimpleJson.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmOptional() throws IOException { var bean = SerTestHelper.testImmOptional(); var json = JodaBeanSer.PRETTY.withIncludeDerived(true).simpleJsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/ImmOptional2.simplejson"); var parsed = JodaBeanSer.PRETTY.simpleJsonReader().read(json, ImmOptional.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmArrays() throws IOException { var bean = ImmArrays.of( new int[] {1, 3, 2}, new long[] {1, 4, 3}, new double[] {1.1, 2.2, 3.3}, new boolean[] {true, false}, new int[][] {{1, 2}, {2}, {}}, new boolean[][] {{true, false}, {false}, {}}); var json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/ImmArrays2.simplejson"); var parsed = JodaBeanSer.PRETTY.simpleJsonReader().read(json, ImmArrays.class); BeanAssert.assertBeanEquals(bean, parsed); var oldParsed = loadAndParse("/org/joda/beans/ser/ImmArrays1.simplejson", ImmArrays.class); BeanAssert.assertBeanEquals(bean, oldParsed); } @Test void test_writeAddress() throws IOException { var bean = SerTestHelper.testAddress(); var json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/Address2.simplejson"); // no round trip with simple JSON, but check that it parses assertThatNoException() .isThrownBy(() -> JodaBeanSer.PRETTY.withDeserializers(SerDeserializers.LENIENT) .simpleJsonReader().read(json, Address.class)); } @Test void test_writeImmAddress() throws IOException { var bean = SerTestHelper.testImmAddress(false).toBuilder() .mapInMap(new HashMap<>()) .beanBeanMap(new HashMap<>()) .build(); var json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/ImmAddress2.simplejson"); // no round trip with simple JSON, but check that it parses assertThatNoException() .isThrownBy(() -> loadAndParse("/org/joda/beans/ser/ImmAddress2.simplejson", ImmAddress.class)); assertThatNoException() .isThrownBy(() -> loadAndParse("/org/joda/beans/ser/ImmAddress1.simplejson", ImmAddress.class)); } @Test void test_writeCollections() throws IOException { var bean = SerTestHelper.testCollections(false); var json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); // System.out.println(json); assertEqualsSerialization(json, "/org/joda/beans/ser/Collections2.simplejson"); var parsed = JodaBeanSer.PRETTY.simpleJsonReader().read(json, ImmGuava.class); BeanAssert.assertBeanEquals(bean, parsed); } private void assertEqualsSerialization(String json, String expectedResource) throws IOException { var url = TestSerializeJson.class.getResource(expectedResource); var expected = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); assertThat(json.trim().replace(System.lineSeparator(), "\n")) .isEqualTo(expected.trim().replace(System.lineSeparator(), "\n")); } private T loadAndParse(String expectedResource, Class type) throws IOException { var url = TestSerializeJson.class.getResource(expectedResource); var text = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); return JodaBeanSer.PRETTY.simpleJsonReader().read(text, type); } //----------------------------------------------------------------------- @Test void test_readWriteBeanEmptyChild_pretty() { var bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", new HashMap()); var json = JodaBeanSer.PRETTY.simpleJsonWriter().write(bean); assertThat(json).isEqualTo("{\n \"element\": \"Test\",\n \"child\": {}\n}\n"); var parsed = JodaBeanSer.PRETTY.simpleJsonReader().read(json, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWriteBeanEmptyChild_compact() { var bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", new HashMap()); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo("{\"element\":\"Test\",\"child\":{}}"); var parsed = JodaBeanSer.COMPACT.simpleJsonReader().read(json, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_primitiveTypeChanged() throws IOException { var json = "{\"a\":6,\"b\":5}"; var parsed = JodaBeanSer.COMPACT.simpleJsonReader().read(json, ImmDoubleFloat.class); assertThat(parsed.getA()).isCloseTo(6, offset(1e-10)); assertThat(parsed.getB()).isCloseTo(5, offset(1e-10)); } //----------------------------------------------------------------------- @Test void test_readWrite_boolean_true() { var bean = new FlexiBean(); bean.set("data", Boolean.TRUE); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo("{\"data\":true}"); var parsed = JodaBeanSer.COMPACT.simpleJsonReader().read(new StringReader(json), FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_boolean_false() { var bean = new FlexiBean(); bean.set("data", Boolean.FALSE); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo("{\"data\":false}"); var parsed = JodaBeanSer.COMPACT.simpleJsonReader().read(new StringReader(json), FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //------------------------------------------------------------------------- @Test void test_write_doubleObject() { var bean = new FlexiBean(); bean.set("data", (double) 6); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"data":6.0}"""); } @Test void test_write_doubleObject_NaN() { var bean = new FlexiBean(); bean.set("data", Double.NaN); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"data":"NaN"}"""); } @Test void test_write_doubleObject_NaN_compatible() { var bean = new FlexiBean(); bean.set("data", Double.NaN); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.COMPATIBLE_V2).simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"data":null}"""); } @Test void test_write_doubleObject_PositiveInfinity() { var bean = new FlexiBean(); bean.set("data", Double.POSITIVE_INFINITY); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"data":"Infinity"}"""); } @Test void test_write_doubleObject_NegativeInfinity() { var bean = new FlexiBean(); bean.set("data", Double.NEGATIVE_INFINITY); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"data":"-Infinity"}"""); } @Test void test_readWrite_double_NaN() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":"NaN","valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NaN_compatible() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.COMPATIBLE_V2).simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":null,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NaN_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NaN); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.LITERAL).simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":NaN,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_PositiveInfinity_string() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.POSITIVE_INFINITY); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":"Infinity","valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_PositiveInfinity_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.POSITIVE_INFINITY); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.LITERAL).simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":Infinity,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_double_PositiveInfinity_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.POSITIVE_INFINITY); var json = """ {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":+Infinity,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""; var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NegativeInfinity_string() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NEGATIVE_INFINITY); var json = JodaBeanSer.COMPACT.simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":"-Infinity","valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_double_NegativeInfinity_literal() { var bean = new PrimitiveBean(); bean.setValueDouble(Double.NEGATIVE_INFINITY); var json = JodaBeanSer.COMPACT.withJsonNumberFormat(JodaBeanJsonNumberFormat.LITERAL).simpleJsonWriter().write(bean); assertThat(json).isEqualTo(""" {"valueLong":0,"valueInt":0,"valueShort":0,"valueByte":0,\ "valueDouble":-Infinity,"valueFloat":0.0,"valueChar":"\\u0000","valueBoolean":false}"""); var parsed = JodaBeanSer.COMPACT.jsonReader().read(json, PrimitiveBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_emptyFlexiBean() { var parsed = JodaBeanSer.COMPACT.simpleJsonReader().read("{}", FlexiBean.class); BeanAssert.assertBeanEquals(new FlexiBean(), parsed); } @Test void test_read_rootTypeArgumentIncorrect() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.simpleJsonReader().read("{}", Integer.class)); } @Test void test_write_nullKeyInMap() { var address = new Address(); var bean = new Person(); bean.getOtherAddressMap().put(null, address); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.simpleJsonWriter().write(bean)); } //----------------------------------------------------------------------- static Object[][] data_badFormat() { return new Object[][] { {"{,}"}, {"{1,2}"}, {"{\"a\",6}"}, {"{\"a\":[}}"}, }; } @ParameterizedTest @MethodSource("data_badFormat") void test_badFormat(String text) throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.simpleJsonReader().read(text, FlexiBean.class)); } //----------------------------------------------------------------------- @Test void test_writer_nullSettings() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonWriter(null)); } @Test void test_writer_write1_nullBean() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonWriter(JodaBeanSer.PRETTY).write(null)); } @Test void test_writer_write2_nullBean() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonWriter(JodaBeanSer.PRETTY).write(null, new StringBuilder())); } @Test void test_writer_write2_nullAppendable() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonWriter(JodaBeanSer.PRETTY).write(new FlexiBean(), null)); } //----------------------------------------------------------------------- @Test void test_reader_nullSettings() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(null)); } @Test void test_reader_readReader_null() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(JodaBeanSer.PRETTY).read((Reader) null, FlexiBean.class)); } @Test void test_reader_readString_null() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(JodaBeanSer.PRETTY).read((String) null, FlexiBean.class)); } @Test void test_reader_readReaderType_nullReader() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(JodaBeanSer.PRETTY).read((Reader) null, Bean.class)); } @Test void test_reader_readReaderType_nullType() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(JodaBeanSer.PRETTY).read(new StringReader(""), null)); } @Test void test_reader_readStringType_nullString() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(JodaBeanSer.PRETTY).read((String) null, Bean.class)); } @Test void test_reader_readStringType_nullType() throws IOException { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleJsonReader(JodaBeanSer.PRETTY).read("", null)); } } ================================================ FILE: src/test/java/org/joda/beans/ser/lowerCase.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser; /** * Mock class with a silly name. */ class lowerCase { } ================================================ FILE: src/test/java/org/joda/beans/ser/map/TestSerializeSimpleMap.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.entry; import java.util.HashMap; import java.util.Map; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmGuava; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.Person; import org.joda.beans.sample.SimpleJson; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerTestHelper; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableMap; /** * Test property roundtrip using a map-structure. */ class TestSerializeSimpleMap { @Test void test_writeSimpleJson() { SimpleJson bean = SerTestHelper.testSimpleJson(); Map map = JodaBeanSer.PRETTY.simpleMapWriter().write(bean); // System.out.println(map); SimpleJson parsed = JodaBeanSer.PRETTY.simpleMapReader().read(map, SimpleJson.class); // System.out.println(bean); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmOptional() { ImmOptional bean = SerTestHelper.testImmOptional(); Map map = JodaBeanSer.PRETTY.withIncludeDerived(true).simpleMapWriter().write(bean); // System.out.println(map); ImmOptional parsed = JodaBeanSer.PRETTY.simpleMapReader().read(map, ImmOptional.class); // System.out.println(bean); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeCollections() { ImmGuava bean = SerTestHelper.testCollections(false); Map map = JodaBeanSer.PRETTY.simpleMapWriter().write(bean); // System.out.println(map); @SuppressWarnings("unchecked") ImmGuava parsed = JodaBeanSer.PRETTY.simpleMapReader().read(map, ImmGuava.class); // System.out.println(bean); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_readWriteBeanEmptyChild() { FlexiBean bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", new HashMap()); Map map = JodaBeanSer.PRETTY.simpleMapWriter().write(bean); assertThat(map).containsOnly(entry("element", "Test"), entry("child", ImmutableMap.of())); FlexiBean parsed = JodaBeanSer.PRETTY.simpleMapReader().read(map, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_readWrite_boolean_true() { FlexiBean bean = new FlexiBean(); bean.set("data", Boolean.TRUE); Map map = JodaBeanSer.COMPACT.simpleMapWriter().write(bean); assertThat(map).containsOnly(entry("data", Boolean.TRUE)); FlexiBean parsed = JodaBeanSer.COMPACT.simpleMapReader().read(map, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWrite_boolean_false() { FlexiBean bean = new FlexiBean(); bean.set("data", Boolean.FALSE); Map map = JodaBeanSer.COMPACT.simpleMapWriter().write(bean); assertThat(map).containsOnly(entry("data", Boolean.FALSE)); FlexiBean parsed = JodaBeanSer.COMPACT.simpleMapReader().read(map, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_emptyFlexiBean() { FlexiBean parsed = JodaBeanSer.COMPACT.simpleMapReader().read(new HashMap<>(), FlexiBean.class); BeanAssert.assertBeanEquals(new FlexiBean(), parsed); } @Test void test_read_rootTypeArgumentIncorrect() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.simpleMapReader().read(new HashMap<>(), Integer.class)); } @Test void test_write_nullKeyInMap() { Address address = new Address(); Person bean = new Person(); bean.getOtherAddressMap().put(null, address); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.simpleMapWriter().write(bean)); } //----------------------------------------------------------------------- @Test void test_writer_nullSettings() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleMapWriter(null)); } @Test void test_writer_write_nullBean() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleMapWriter(JodaBeanSer.PRETTY).write(null)); } //----------------------------------------------------------------------- @Test void test_reader_nullSettings() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleMapReader(null)); } @Test void test_reader_read_nullBean() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleMapReader(JodaBeanSer.PRETTY).read(null, FlexiBean.class)); } @Test void test_reader_read_nullType() { assertThatIllegalArgumentException() .isThrownBy(() -> new JodaBeanSimpleMapReader(JodaBeanSer.PRETTY).read(new HashMap<>(), null)); } } ================================================ FILE: src/test/java/org/joda/beans/ser/xml/MockRenameDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.ser.DefaultDeserializer; import org.joda.beans.ser.SerDeserializer; /** * Mock deserializer that handles a renamed property. */ class MockRenameDeserializer extends DefaultDeserializer { /** * Singleton. */ static final SerDeserializer INSTANCE = new MockRenameDeserializer(); /** * Creates an instance. */ protected MockRenameDeserializer() { } //----------------------------------------------------------------------- @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { if ("firstName".equals(propertyName)) { return metaBean.metaProperty("forename"); } return super.findMetaProperty(beanType, metaBean, propertyName); } } ================================================ FILE: src/test/java/org/joda/beans/ser/xml/MockSemanticChangeDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.impl.BufferingBeanBuilder; import org.joda.beans.sample.SimplePerson; import org.joda.beans.ser.DefaultDeserializer; import org.joda.beans.ser.SerDeserializer; /** * Mock deserializer that handles a semantic change. */ class MockSemanticChangeDeserializer extends DefaultDeserializer { /** * Singleton. */ static final SerDeserializer INSTANCE = new MockSemanticChangeDeserializer(); /** * Creates an instance. */ protected MockSemanticChangeDeserializer() { } //----------------------------------------------------------------------- @Override public BeanBuilder createBuilder(Class beanType, MetaBean metaBean) { return BufferingBeanBuilder.of(metaBean); } @Override public Object build(Class beanType, BeanBuilder builder) { BufferingBeanBuilder bld = (BufferingBeanBuilder) builder; if ("Stephen".equals(bld.getBuffer().get(SimplePerson.meta().forename())) && "Colebourne".equals(bld.getBuffer().get(SimplePerson.meta().surname()))) { bld.set(SimplePerson.meta().forename(), "Steve"); } return bld.build(); } } ================================================ FILE: src/test/java/org/joda/beans/ser/xml/MockTypeChangeDeserializer.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import org.joda.beans.BeanBuilder; import org.joda.beans.MetaBean; import org.joda.beans.MetaProperty; import org.joda.beans.impl.StandaloneMetaProperty; import org.joda.beans.sample.SimplePerson; import org.joda.beans.ser.DefaultDeserializer; import org.joda.beans.ser.SerDeserializer; /** * Mock deserializer that handles a renamed property. */ class MockTypeChangeDeserializer extends DefaultDeserializer { /** * Singleton. */ static final SerDeserializer INSTANCE = new MockTypeChangeDeserializer(); /** * The number of cars String property. */ private MetaProperty NUMBER_OF_CARS_STRING = StandaloneMetaProperty.of("numberOfCars", SimplePerson.meta(), String.class); /** * Creates an instance. */ protected MockTypeChangeDeserializer() { } //----------------------------------------------------------------------- @Override public MetaProperty findMetaProperty(Class beanType, MetaBean metaBean, String propertyName) { if ("numberOfCars".equals(propertyName)) { return NUMBER_OF_CARS_STRING; } return super.findMetaProperty(beanType, metaBean, propertyName); } @Override public void setValue(BeanBuilder builder, MetaProperty metaProp, Object value) { Object valueToSet = value; if (metaProp == NUMBER_OF_CARS_STRING && value != null) { String oldValue = value.toString(); if (oldValue.equals("None")) { valueToSet = 0; } else if (oldValue.equals("One")) { valueToSet = 1; } else if (oldValue.equals("Two")) { valueToSet = 2; } else if (oldValue.equals("Lots")) { valueToSet = 3; } } super.setValue(builder, metaProp, valueToSet); } } ================================================ FILE: src/test/java/org/joda/beans/ser/xml/TestDeserializeXml.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import static org.assertj.core.api.Assertions.assertThatRuntimeException; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.SimplePerson; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerDeserializers; import org.joda.beans.test.BeanAssert; import org.joda.convert.RenameHandler; import org.junit.jupiter.api.Test; /** * Test deserialization using XML. */ class TestDeserializeXml { @Test void test_read_renamedType() { String xml = "Smith"; assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class)); RenameHandler.INSTANCE.renamedType("org.jodabeans.FlexibleBean", FlexiBean.class); FlexiBean parsed = JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class); FlexiBean expected = new FlexiBean(); expected.set("surname", "Smith"); BeanAssert.assertBeanEquals(expected, parsed); } @Test void test_read_renamedTypeLower() { String xml = "" + "Smith" + "Jones" + ""; assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class)); RenameHandler.INSTANCE.renamedType("org.jodabeans.SPerson", SimplePerson.class); FlexiBean parsed = JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class); FlexiBean expected = new FlexiBean(); SimplePerson person1 = new SimplePerson(); person1.setSurname("Smith"); SimplePerson person2 = new SimplePerson(); person2.setSurname("Jones"); expected.set("extra", person1); expected.set("person", person2); BeanAssert.assertBeanEquals(expected, parsed); } @Test void test_read_withSemanticChangeDeserializer() { SerDeserializers desers = new SerDeserializers(); desers.register(SimplePerson.class, MockSemanticChangeDeserializer.INSTANCE); String xml = "" + "JohnSmith" + "StephenColebourne" + ""; FlexiBean parsed = JodaBeanSer.COMPACT.withDeserializers(desers).xmlReader().read(xml, FlexiBean.class); FlexiBean expected = new FlexiBean(); SimplePerson person1 = new SimplePerson(); person1.setForename("John"); person1.setSurname("Smith"); SimplePerson person2 = new SimplePerson(); person2.setForename("Steve"); // changed person2.setSurname("Colebourne"); expected.set("person1", person1); expected.set("person2", person2); BeanAssert.assertBeanEquals(expected, parsed); } @Test void test_read_withRenameDeserializer() { SerDeserializers desers = new SerDeserializers(); desers.register(SimplePerson.class, MockRenameDeserializer.INSTANCE); String xml = "" + "JohnSmith" + "StephenColebourne" + ""; FlexiBean parsed = JodaBeanSer.COMPACT.withDeserializers(desers).xmlReader().read(xml, FlexiBean.class); FlexiBean expected = new FlexiBean(); SimplePerson person1 = new SimplePerson(); person1.setForename("John"); person1.setSurname("Smith"); SimplePerson person2 = new SimplePerson(); person2.setForename("Stephen"); person2.setSurname("Colebourne"); expected.set("person1", person1); expected.set("person2", person2); BeanAssert.assertBeanEquals(expected, parsed); } @Test void test_read_withTypeChangeDeserializer() { SerDeserializers desers = new SerDeserializers(); desers.register(SimplePerson.class, MockTypeChangeDeserializer.INSTANCE); String xml = "" + "NoneSmith" + "TwoColebourne" + ""; FlexiBean parsed = JodaBeanSer.COMPACT.withDeserializers(desers).xmlReader().read(xml, FlexiBean.class); FlexiBean expected = new FlexiBean(); SimplePerson person1 = new SimplePerson(); person1.setNumberOfCars(0); person1.setSurname("Smith"); SimplePerson person2 = new SimplePerson(); person2.setNumberOfCars(2); person2.setSurname("Colebourne"); expected.set("person1", person1); expected.set("person2", person2); BeanAssert.assertBeanEquals(expected, parsed); } @Test void test_read_withBadEntity() { SerDeserializers desers = new SerDeserializers(); desers.register(SimplePerson.class, MockTypeChangeDeserializer.INSTANCE); String xml = "" + ""; for (int i = 99; i > 0; i--) { xml += ""; } xml += "]>" + "NoneSmith &x1;" + "TwoColebourne" + ""; String finalXml = xml; assertThatRuntimeException() .isThrownBy(() -> JodaBeanSer.COMPACT.withDeserializers(desers).xmlReader().read(finalXml, FlexiBean.class)); } } ================================================ FILE: src/test/java/org/joda/beans/ser/xml/TestSerializeXml.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.ser.xml; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.offset; import java.io.CharArrayWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.joda.beans.Bean; import org.joda.beans.impl.flexi.FlexiBean; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmAddress; import org.joda.beans.sample.ImmDoubleFloat; import org.joda.beans.sample.ImmEmpty; import org.joda.beans.sample.ImmGenericCollections; import org.joda.beans.sample.ImmKey; import org.joda.beans.sample.ImmMappedKey; import org.joda.beans.sample.ImmOptional; import org.joda.beans.sample.ImmPerson; import org.joda.beans.sample.JodaConvertBean; import org.joda.beans.sample.JodaConvertInterface; import org.joda.beans.sample.JodaConvertWrapper; import org.joda.beans.sample.Person; import org.joda.beans.sample.SimpleName; import org.joda.beans.sample.SimplePerson; import org.joda.beans.ser.JodaBeanSer; import org.joda.beans.ser.SerDeserializers; import org.joda.beans.ser.SerTestHelper; import org.joda.beans.test.BeanAssert; import org.junit.jupiter.api.Test; import com.google.common.collect.ImmutableMap; import com.google.common.io.Resources; /** * Test property roundtrip using XML. */ class TestSerializeXml { @Test void test_writeAddress() throws IOException { var bean = SerTestHelper.testAddress(); var xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); // System.out.println(xml); assertEqualsSerialization(xml, "/org/joda/beans/ser/Address.xml"); var parsed = (Address) JodaBeanSer.PRETTY.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeToAppendable() throws IOException { var bean = SerTestHelper.testAddress(); var output = new CharArrayWriter(); JodaBeanSer.PRETTY.xmlWriter().write(bean, output); var xml = output.toString(); var parsed = (Address) JodaBeanSer.PRETTY.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmAddress() throws IOException { var bean = SerTestHelper.testImmAddress(false); var xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); // System.out.println(xml); assertEqualsSerialization(xml, "/org/joda/beans/ser/ImmAddress.xml"); xml = xml.replace("185", "185"); var parsed = (ImmAddress) JodaBeanSer.PRETTY.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeImmOptional() throws IOException { var bean = SerTestHelper.testImmOptional(); var xml = JodaBeanSer.PRETTY.withIncludeDerived(true).xmlWriter().write(bean); // System.out.println(xml); assertEqualsSerialization(xml, "/org/joda/beans/ser/ImmOptional.xml"); var parsed = (ImmOptional) JodaBeanSer.PRETTY.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeCollections() throws IOException { var bean = SerTestHelper.testCollections(true); var xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); // System.out.println(xml); assertEqualsSerialization(xml, "/org/joda/beans/ser/Collections.xml"); var parsed = JodaBeanSer.PRETTY.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_writeJodaConvertInterface() { var bean = SerTestHelper.testGenericInterfaces(); var xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); // System.out.println(xml); @SuppressWarnings("unchecked") var parsed = (ImmGenericCollections) JodaBeanSer.COMPACT.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } private void assertEqualsSerialization(String xml, String expectedResource) throws IOException { var url = TestSerializeXml.class.getResource(expectedResource); var expected = Resources.asCharSource(url, StandardCharsets.UTF_8).read(); assertThat(xml.trim().replace(System.lineSeparator(), "\n")) .isEqualTo(expected.trim().replace(System.lineSeparator(), "\n")); } //----------------------------------------------------------------------- @Test void test_readWriteBeanEmptyChild_pretty() { var bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", ImmEmpty.builder().build()); var xml = JodaBeanSer.PRETTY.xmlWriter().write(bean); assertThat(xml) .isEqualTo(""" Test """); var parsed = JodaBeanSer.PRETTY.xmlReader().read(xml, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWriteBeanEmptyChild_compact() { var bean = new FlexiBean(); bean.set("element", "Test"); bean.set("child", ImmEmpty.builder().build()); var xml = JodaBeanSer.COMPACT.xmlWriter().write(bean); assertThat(xml) .isEqualTo("" + "" + "Test"); var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWriteJodaConvertWrapper() { var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); var xml = JodaBeanSer.COMPACT.xmlWriter().write(wrapper); assertThat(xml) .isEqualTo("" + "" + "Hello:9Weird"); var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_readWriteJodaConvertBean() { var bean = new JodaConvertBean("Hello:9"); var xml = JodaBeanSer.COMPACT.xmlWriter().write(bean); assertThat(xml) .isEqualTo("" + "" + "Hello9"); var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_primitiveTypeChanged() throws IOException { var xml = "65"; var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml, ImmDoubleFloat.class); assertThat(parsed.getA()).isCloseTo(6, offset(1e-10)); assertThat(parsed.getB()).isCloseTo(5, offset(1e-10)); } //----------------------------------------------------------------------- @Test void test_read_nonStandard_JodaConvertWrapper_expanded() { var xml = "" + "" + "Hello9Weird"; var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml); var wrapper = new JodaConvertWrapper(); var bean = new JodaConvertBean("Hello:9"); wrapper.setBean(bean); wrapper.setDescription("Weird"); BeanAssert.assertBeanEquals(wrapper, parsed); } @Test void test_read_nonStandard_JodaConvertBean_flattened() { var xml = "" + "Hello:9"; var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml); var bean = new JodaConvertBean("Hello:9"); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_nonStandard_withCommentBeanRoot() { var xml = "Test"; var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class); var bean = new FlexiBean(); bean.set("element", "Test"); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_nonStandard_withCommentInProperty() { var xml = "Test"; var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml, FlexiBean.class); var bean = new FlexiBean(); bean.set("element", "Test"); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_aliased() { var xml = "" + "" + "AB"; var parsed = JodaBeanSer.COMPACT.xmlReader().read(xml); var bean = new SimpleName(); bean.setForename("A"); bean.setSurname("B"); BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_readWriteInterfaceKeyMap() { var key1 = ImmKey.builder().name("Alpha").build(); var person1 = ImmPerson.builder().forename("Bob").surname("Builder").build(); var key2 = ImmKey.builder().name("Beta").build(); var person2 = ImmPerson.builder().forename("Dana").surname("Dash").build(); var mapped = ImmMappedKey.builder().data(ImmutableMap.of(key1, person1, key2, person2)).build(); var xml = JodaBeanSer.PRETTY.xmlWriter().write(mapped); var bean = (ImmMappedKey) JodaBeanSer.PRETTY.xmlReader().read(xml); BeanAssert.assertBeanEquals(bean, mapped); } @Test void test_read_badTypeInMap() { var xml = "work" + "BIGWIG"; var parsed = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT).xmlReader().read(xml, FlexiBean.class); var bean = new FlexiBean(); bean.set("element", ImmutableMap.of("work", "BIGWIG")); // converted to a string BeanAssert.assertBeanEquals(bean, parsed); } @Test void test_read_ignoreProperty() { var xml = "fooignored"; var parsed = JodaBeanSer.COMPACT.withDeserializers(SerDeserializers.LENIENT).xmlReader().read(xml, ImmKey.class); var bean = ImmKey.builder().name("foo").build(); BeanAssert.assertBeanEquals(bean, parsed); } //----------------------------------------------------------------------- @Test void test_read_noBeanElementAtRoot() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader().read("", Bean.class)); } @Test void test_read_noTypeAttributeAtRoot() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader().read("", Bean.class)); } @Test void test_read_noTypeAttributeAtRootButTypeSpecified() { FlexiBean parsed = JodaBeanSer.COMPACT.xmlReader().read("", FlexiBean.class); BeanAssert.assertBeanEquals(new FlexiBean(), parsed); } @Test void test_read_rootTypeAttributeNotBean() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader() .read("", Bean.class)); } @Test void test_read_rootTypeInvalid() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader() .read("", SimplePerson.class)); } @Test void test_read_rootTypeArgumentInvalid() { assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlReader().read("", Integer.class)); } @Test void test_write_nullKeyInMap() { var address = new Address(); var bean = new Person(); bean.getOtherAddressMap().put(null, address); assertThatIllegalArgumentException() .isThrownBy(() -> JodaBeanSer.COMPACT.xmlWriter().write(bean)); } } ================================================ FILE: src/test/java/org/joda/beans/test/TestBeanAssert.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.test; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatNoException; import org.joda.beans.sample.Address; import org.joda.beans.sample.ImmTolerance; import org.joda.beans.sample.Person; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test {@link BeanAssert}. */ class TestBeanAssert { private Person person1; private Person person2; @BeforeEach void setUp() { person1 = new Person(); person1.setForename("Vince"); person1.setSurname("Cable"); person1.setNumberOfCars(1); person1.getAddressList().add(new Address()); person1.getAddressList().get(0).setNumber(12); person1.getAddressList().get(0).setStreet("Play Street"); person1.getAddressList().get(0).setCity("Toytown"); person1.getAddressList().get(0).setOwner(new Person()); person1.getAddressList().get(0).getOwner().setForename("Nick"); person1.getAddressList().get(0).getOwner().setSurname("Clegg"); person1.setMainAddress(new Address()); person1.getMainAddress().setStreet("Party Road"); person1.getMainAddress().setCity("Gamesville"); person1.getMainAddress().setOwner(new Person()); person1.getMainAddress().getOwner().setForename("Simon"); person1.getMainAddress().getOwner().setForename("Hughes"); person1.getOtherAddressMap().put("Home", new Address()); person1.getOtherAddressMap().get("Home").setNumber(999); person1.getOtherAddressMap().get("Home").setStreet("Upper Lane"); person1.getOtherAddressMap().get("Home").setCity("Skyton"); person2 = new Person(); person2.setForename("Vince"); person2.setSurname("Cable"); person2.setNumberOfCars(1); person2.getAddressList().add(new Address()); person2.getAddressList().get(0).setNumber(12); person2.getAddressList().get(0).setStreet("Play Street"); person2.getAddressList().get(0).setCity("Toytown"); person2.getAddressList().get(0).setOwner(new Person()); person2.getAddressList().get(0).getOwner().setForename("Nick"); person2.getAddressList().get(0).getOwner().setSurname("Clegg"); person2.setMainAddress(new Address()); person2.getMainAddress().setStreet("Party Road"); person2.getMainAddress().setCity("Gamesville"); person2.getMainAddress().setOwner(new Person()); person2.getMainAddress().getOwner().setForename("Simon"); person2.getMainAddress().getOwner().setForename("Hughes"); person2.getOtherAddressMap().put("Home", new Address()); person2.getOtherAddressMap().get("Home").setNumber(999); person2.getOtherAddressMap().get("Home").setStreet("Upper Lane"); person2.getOtherAddressMap().get("Home").setCity("Skyton"); } @Test void test_same() { BeanAssert.assertBeanEquals(person1, person1); } @Test void test_equal() { BeanAssert.assertBeanEquals(person1, person2); } @Test void test_bean_oneField() { person2.setForename("Bug1"); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(person1, person2)) .withMessage(""" Bean did not equal expected. Differences: .forename: Content differs, expected String but was """); } @Test void test_bean_twoFields() { person2.setForename("Bug1"); person2.setSurname("Bug2"); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(person1, person2)) .withMessage(""" Bean did not equal expected. Differences: .forename: Content differs, expected String but was .surname: Content differs, expected String but was """); } @Test void test_bean_bug_embedded() { person2.getAddressList().get(0).setNumber(234); person2.getMainAddress().setCity("Bug3"); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(person1, person2)) .withMessage(""" Bean did not equal expected. Differences: .addressList[0].number: Content differs, expected Integer <12> but was <234> .mainAddress.city: Content differs, expected String but was """); } @Test void test_bean_sizes() { Address address = new Address(); address.setCity("Nowhere"); person2.getOtherAddressMap().put("Bug", address); person2.getAddressList().clear(); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(person1, person2)) .withMessage(""" Bean did not equal expected. Differences: .addressList: List size differs, expected 1 but was 0 .otherAddressMap: Map size differs, expected 1 but was 2"""); } @Test void test_bean_map() { person2.getOtherAddressMap().get("Home").setCity("Bug"); person2.getOtherAddressMap().get("Home").setOwner(new Person()); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(person1, person2)) .withMessage(""" Bean did not equal expected. Differences: .otherAddressMap[Home].city: Content differs, expected String but was .otherAddressMap[Home].owner: Expected null, but was \ Person """); } @Test void test_beanFullDetail_twoFields() { person2.setForename("Bug1"); person2.setSurname("Bug2"); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEqualsFullDetail(person1, person2)) .withMessage(""" Bean did not equal expected. Differences: .forename: Content differs, expected String but was .surname: Content differs, expected String but was """); } //----------------------------------------------------------------------- @Test void test_bean_oneField_double() { ImmTolerance t1 = ImmTolerance.builder().value(0.015d).build(); ImmTolerance t2 = ImmTolerance.builder().value(0.016d).build(); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2)) .withMessage(""" Bean did not equal expected. Differences: .value: Content differs, expected Double <0.015> but was <0.016>"""); } @Test void test_bean_oneField_double_withinToleranceUp() { ImmTolerance t1 = ImmTolerance.builder().value(0.015d).build(); ImmTolerance t2 = ImmTolerance.builder().value(0.0151d).build(); assertThatNoException().isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2, 0.0002d)); } @Test void test_bean_oneField_double_withinToleranceDown() { ImmTolerance t1 = ImmTolerance.builder().value(0.015d).build(); ImmTolerance t2 = ImmTolerance.builder().value(0.0149d).build(); assertThatNoException().isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2, 0.0002d)); } @Test void test_bean_oneField_double_notInTolerance() { ImmTolerance t1 = ImmTolerance.builder().value(0.015d).build(); ImmTolerance t2 = ImmTolerance.builder().value(0.0153d).build(); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2, 0.0002d)) .withMessage(""" Bean did not equal expected. Differences: .value: Double values differ by more than allowed tolerance, expected Double <0.015> but was <0.0153>"""); } //----------------------------------------------------------------------- @Test void test_bean_oneField_doubleArray() { ImmTolerance t1 = ImmTolerance.builder().array(new double[] {0.015d, 0.015d}).build(); ImmTolerance t2 = ImmTolerance.builder().array(new double[] {0.015d, 0.016d}).build(); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2)) .withMessage(""" Bean did not equal expected. Differences: .array: Content differs, expected \ double[] <[0.015, 0.015]> but was <[0.015, 0.016]>"""); } @Test void test_bean_oneField_doubleArray_withinToleranceUp() { ImmTolerance t1 = ImmTolerance.builder().array(new double[] {0.015d, 0.015d}).build(); ImmTolerance t2 = ImmTolerance.builder().array(new double[] {0.015d, 0.0151d}).build(); assertThatNoException().isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2, 0.0002d)); } @Test void test_bean_oneField_doubleArray_withinToleranceDown() { ImmTolerance t1 = ImmTolerance.builder().array(new double[] {0.015d, 0.015d}).build(); ImmTolerance t2 = ImmTolerance.builder().array(new double[] {0.015d, 0.0149d}).build(); assertThatNoException().isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2, 0.0002d)); } @Test void test_bean_oneField_doubleArray_notInTolerance() { ImmTolerance t1 = ImmTolerance.builder().array(new double[] {0.015d, 0.015d}).build(); ImmTolerance t2 = ImmTolerance.builder().array(new double[] {0.015d, 0.0153d}).build(); assertThatExceptionOfType(BeanComparisonError.class) .isThrownBy(() -> BeanAssert.assertBeanEquals(t1, t2, 0.0002d)) .withMessage(""" Bean did not equal expected. Differences: .array: Double arrays differ by \ more than allowed tolerance, expected double[] <[0.015, 0.015]> but was <[0.015, 0.0153]>"""); } } ================================================ FILE: src/test/java/org/joda/beans/test/TestCoverage.java ================================================ /* * Copyright 2001-present Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.beans.test; import static org.assertj.core.api.Assertions.assertThatNoException; import org.joda.beans.sample.Address; import org.joda.beans.sample.MutableBaseBean; import org.joda.beans.sample.MutableDerivedBean; import org.joda.beans.sample.Person; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test code coverage helper. */ class TestCoverage { private Person person; private MutableBaseBean mutableBase; private MutableDerivedBean mutableDerived; @BeforeEach void setUp() { person = new Person(); person.setForename("Vince"); person.setSurname("Cable"); person.setNumberOfCars(1); person.getAddressList().add(new Address()); person.getAddressList().get(0).setNumber(12); person.getAddressList().get(0).setStreet("Play Street"); person.getAddressList().get(0).setCity("Toytown"); person.getAddressList().get(0).setOwner(new Person()); person.getAddressList().get(0).getOwner().setForename("Nick"); person.getAddressList().get(0).getOwner().setSurname("Clegg"); person.setMainAddress(new Address()); person.getMainAddress().setStreet("Party Road"); person.getMainAddress().setCity("Gamesville"); person.getMainAddress().setOwner(new Person()); person.getMainAddress().getOwner().setForename("Simon"); person.getMainAddress().getOwner().setForename("Hughes"); person.getOtherAddressMap().put("Home", new Address()); person.getOtherAddressMap().get("Home").setNumber(999); person.getOtherAddressMap().get("Home").setStreet("Upper Lane"); person.getOtherAddressMap().get("Home").setCity("Skyton"); mutableBase = MutableBaseBean.builder() .baseBeanString("HopeNotHate") .build(); mutableDerived = (MutableDerivedBean) MutableDerivedBean.builder() .baseBeanString("HopeNotHate") .build(); } @Test void test_coveragePerson() { assertThatNoException().isThrownBy(() -> JodaBeanTests.coverMutableBean(person)); } @Test void test_coverageMutableBase() { assertThatNoException().isThrownBy(() -> JodaBeanTests.coverMutableBean(mutableBase)); } @Test void test_coverageMutableDerived() { assertThatNoException().isThrownBy(() -> JodaBeanTests.coverMutableBean(mutableDerived)); } } ================================================ FILE: src/test/resources/META-INF/org/joda/beans/JodaBeans.ini ================================================ # Test [deserializers] org.joda.beans.sample.ImmKey org.joda.beans.sample.ImmKeyHolder org.joda.beans.sample.Pair = org.joda.beans.sample.PairDeserializer ================================================ FILE: src/test/resources/org/joda/beans/ser/Address.xml ================================================ 251 Big Road London & Capital of the World <!> Etienne Colebourne 0 65432 Big Road Bigton 185 Park Street London OpenGamma 185 Park Street London OpenGamma 65432 Big Road Bigton 65432 Big Road Bigton 185 Park Street London OpenGamma 185 Park Street London OpenGamma joda 21 B OpenGamma ================================================ FILE: src/test/resources/org/joda/beans/ser/Address1.packbinstr ================================================ arr (3) - int 3 - str 'org.joda.beans.sample.' - @type Address bean (4) - str 'number' - str 'street' - str 'city' - str 'owner' - int 251 - str 'Big Road' - str 'London & Capital of the World ' - @type Person bean (8) - str 'forename' - str 'surname' - str 'numberOfCars' - str 'addressList' - str 'otherAddressMap' - str 'addressesList' - str 'mainAddress' - str 'extensions' - str 'Etienne' - str 'Colebourne' - int 0 - arr (3) - arr (4) - int 65432 - ref 5 'Big Road' - str 'Bigton' - null - null - @type CompanyAddress bean (5) - ref 1 'number' - ref 2 'street' - ref 3 'city' - ref 4 'owner' - str 'companyName' - int 185 - str 'Park Street' - str 'London' - null - str 'OpenGamma' - map (3) = str 'other' null = str 'work' @typeref 2 CompanyAddress arr (5) - int 185 - ref 19 'Park Street' - ref 20 'London' - null - ref 21 'OpenGamma' = str 'home' arr (4) - int 65432 - ref 5 'Big Road' - ref 17 'Bigton' - null - arr (1) - arr (2) - arr (4) - int 65432 - ref 5 'Big Road' - ref 17 'Bigton' - null - @typeref 2 CompanyAddress arr (5) - int 185 - ref 19 'Park Street' - ref 20 'London' - null - ref 21 'OpenGamma' - @typeref 2 CompanyAddress arr (5) - int 185 - ref 19 'Park Street' - ref 20 'London' - null - ref 21 'OpenGamma' - map (4) = str 'interests' str 'joda' = str 'conferenceCount' int 21 = str 'quality' chr B = str 'company' @type Company bean (1) - ref 18 'companyName' - ref 21 'OpenGamma' ================================================ FILE: src/test/resources/org/joda/beans/ser/Address2.binstr ================================================ arr (2) - int 1 - map (5) = ext type=32 'org.joda.beans.sample.Address' (bean) nil = str 'number' int 251 = str 'street' str 'Big Road' = str 'city' str 'London & Capital of the World ' = str 'owner' map (8) = str 'forename' str 'Etienne' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 0 = str 'addressList' arr (3) - map (3) = str 'number' int 65432 = str 'street' str 'Big Road' = str 'city' str 'Bigton' - nil - map (5) = ext type=32 'CompanyAddress' (bean) nil = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London' = str 'companyName' str 'OpenGamma' = str 'otherAddressMap' map (3) = str 'other' nil = str 'work' map (5) = ext type=32 'CompanyAddress' (bean) nil = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London' = str 'companyName' str 'OpenGamma' = str 'home' map (3) = str 'number' int 65432 = str 'street' str 'Big Road' = str 'city' str 'Bigton' = str 'addressesList' arr (1) - arr (2) - map (3) = str 'number' int 65432 = str 'street' str 'Big Road' = str 'city' str 'Bigton' - map (5) = ext type=32 'CompanyAddress' (bean) nil = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London' = str 'companyName' str 'OpenGamma' = str 'mainAddress' map (5) = ext type=32 'CompanyAddress' (bean) nil = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London' = str 'companyName' str 'OpenGamma' = str 'extensions' map (4) = str 'interests' str 'joda' = str 'conferenceCount' int 21 = str 'quality' map (1) = ext type=33 'Character' (data) str 'B' = str 'company' map (2) = ext type=32 'Company' (bean) nil = str 'companyName' str 'OpenGamma' ================================================ FILE: src/test/resources/org/joda/beans/ser/Address2.json ================================================ { "@bean": "org.joda.beans.sample.Address", "number": 251, "street": "Big Road", "city": "London & Capital of the World ", "owner": { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 0, "addressList": [{ "number": 65432, "street": "Big Road", "city": "Bigton" }, null, { "@bean": "CompanyAddress", "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }], "otherAddressMap": { "other": null, "work": { "@bean": "CompanyAddress", "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }, "home": { "number": 65432, "street": "Big Road", "city": "Bigton" } }, "addressesList": [[{ "number": 65432, "street": "Big Road", "city": "Bigton" }, { "@bean": "CompanyAddress", "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }]], "mainAddress": { "@bean": "CompanyAddress", "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }, "extensions": { "interests": "joda", "conferenceCount": 21, "quality": { "@type": "Character", "value": "B" }, "company": { "@bean": "Company", "companyName": "OpenGamma" } } } } ================================================ FILE: src/test/resources/org/joda/beans/ser/Address2.simplejson ================================================ { "number": 251, "street": "Big Road", "city": "London & Capital of the World ", "owner": { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 0, "addressList": [{ "number": 65432, "street": "Big Road", "city": "Bigton" }, null, { "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }], "otherAddressMap": { "other": null, "work": { "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }, "home": { "number": 65432, "street": "Big Road", "city": "Bigton" } }, "addressesList": [[{ "number": 65432, "street": "Big Road", "city": "Bigton" }, { "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }]], "mainAddress": { "number": 185, "street": "Park Street", "city": "London", "companyName": "OpenGamma" }, "extensions": { "interests": "joda", "conferenceCount": 21, "quality": "B", "company": { "companyName": "OpenGamma" } } } } ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections.xml ================================================ A B A B A B A AA B BB A AA B BB A AA B BB A B A C B D A B A C B D A B A C B D A B C A B A B A B A AA B BB A AA B BB A AA B BB A B A C B D A B A C B D A B A C B D BCD
================================================ FILE: src/test/resources/org/joda/beans/ser/Collections1.binstr ================================================ arr (2) - int 1 - map (35) = ext type=32 'org.joda.beans.sample.ImmGuava' (bean) nil = str 'collection' map (1) = ext type=34 'List' (meta) arr (0) = str 'list' arr (2) - map (1) = ext type=33 'String' (data) str 'A' - map (1) = ext type=33 'String' (data) str 'B' = str 'set' arr (2) - map (1) = ext type=33 'String' (data) str 'A' - map (1) = ext type=33 'String' (data) str 'B' = str 'sortedSet' arr (2) - map (1) = ext type=33 'String' (data) str 'A' - map (1) = ext type=33 'String' (data) str 'B' = str 'map' map (2) = map (1) = ext type=33 'String' (data) str 'A' str 'AA' = map (1) = ext type=33 'String' (data) str 'B' str 'BB' = str 'sortedMap' map (2) = map (1) = ext type=33 'String' (data) str 'A' str 'AA' = map (1) = ext type=33 'String' (data) str 'B' str 'BB' = str 'biMap' map (2) = map (1) = ext type=33 'String' (data) str 'A' str 'AA' = map (1) = ext type=33 'String' (data) str 'B' str 'BB' = str 'multimap' map (1) = ext type=34 'ListMultimap' (meta) map (0) = str 'listMultimap' map (0) = str 'setMultimap' map (0) = str 'multiset' map (3) = map (1) = ext type=33 'String' (data) str 'A' int 1 = map (1) = ext type=33 'String' (data) str 'B' int 2 = map (1) = ext type=33 'String' (data) str 'C' int 3 = str 'sortedMultiset' map (0) = str 'collectionInterface' map (1) = ext type=34 'List' (meta) arr (0) = str 'listInterface' arr (2) - map (1) = ext type=33 'String' (data) str 'A' - map (1) = ext type=33 'String' (data) str 'B' = str 'setInterface' arr (2) - map (1) = ext type=33 'String' (data) str 'A' - map (1) = ext type=33 'String' (data) str 'B' = str 'sortedSetInterface' arr (2) - map (1) = ext type=33 'String' (data) str 'A' - map (1) = ext type=33 'String' (data) str 'B' = str 'mapInterface' map (2) = map (1) = ext type=33 'String' (data) str 'A' str 'AA' = map (1) = ext type=33 'String' (data) str 'B' str 'BB' = str 'sortedMapInterface' map (2) = map (1) = ext type=33 'String' (data) str 'A' str 'AA' = map (1) = ext type=33 'String' (data) str 'B' str 'BB' = str 'biMapInterface' map (2) = map (1) = ext type=33 'String' (data) str 'A' str 'AA' = map (1) = ext type=33 'String' (data) str 'B' str 'BB' = str 'multimapInterface' map (1) = ext type=34 'ListMultimap' (meta) map (0) = str 'listMultimapInterface' map (0) = str 'setMultimapInterface' map (0) = str 'multisetInterface' map (0) = str 'sortedMultisetInterface' map (0) = str 'listWildExtendsT' arr (0) = str 'listWildExtendsNumber' arr (0) = str 'listWildExtendsComparable' arr (0) = str 'setWildExtendsT' arr (0) = str 'setWildExtendsNumber' arr (0) = str 'setWildExtendsComparable' arr (0) = str 'listWildBuilder1' arr (0) = str 'listWildBuilder2' arr (0) = str 'mapWildBuilder1' map (0) = str 'mapWildKey' map (0) ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections1.json ================================================ { "@bean": "org.joda.beans.sample.ImmGuava", "collection": { "@meta": "List", "value": [] }, "list": [{ "@type": "String", "value": "A" }, { "@type": "String", "value": "B" }], "set": [{ "@type": "String", "value": "A" }, { "@type": "String", "value": "B" }], "sortedSet": [{ "@type": "String", "value": "A" }, { "@type": "String", "value": "B" }], "map": [[{ "@type": "String", "value": "A" }, "AA"], [{ "@type": "String", "value": "B" }, "BB"]], "sortedMap": [[{ "@type": "String", "value": "A" }, "AA"], [{ "@type": "String", "value": "B" }, "BB"]], "biMap": [[{ "@type": "String", "value": "A" }, "AA"], [{ "@type": "String", "value": "B" }, "BB"]], "multimap": { "@meta": "ListMultimap", "value": [[{ "@type": "String", "value": "A" }, "B"], [{ "@type": "String", "value": "A" }, "C"], [{ "@type": "String", "value": "B" }, "D"]] }, "listMultimap": [[{ "@type": "String", "value": "A" }, "B"], [{ "@type": "String", "value": "A" }, "C"], [{ "@type": "String", "value": "B" }, "D"]], "setMultimap": [[{ "@type": "String", "value": "A" }, "B"], [{ "@type": "String", "value": "A" }, "C"], [{ "@type": "String", "value": "B" }, "D"]], "multiset": [[{ "@type": "String", "value": "A" }, 1], [{ "@type": "String", "value": "B" }, 2], [{ "@type": "String", "value": "C" }, 3]], "sortedMultiset": [], "collectionInterface": { "@meta": "List", "value": [] }, "listInterface": [{ "@type": "String", "value": "A" }, { "@type": "String", "value": "B" }], "setInterface": [{ "@type": "String", "value": "A" }, { "@type": "String", "value": "B" }], "sortedSetInterface": [{ "@type": "String", "value": "A" }, { "@type": "String", "value": "B" }], "mapInterface": [[{ "@type": "String", "value": "A" }, "AA"], [{ "@type": "String", "value": "B" }, "BB"]], "sortedMapInterface": [[{ "@type": "String", "value": "A" }, "AA"], [{ "@type": "String", "value": "B" }, "BB"]], "biMapInterface": [[{ "@type": "String", "value": "A" }, "AA"], [{ "@type": "String", "value": "B" }, "BB"]], "multimapInterface": { "@meta": "ListMultimap", "value": [[{ "@type": "String", "value": "A" }, "B"], [{ "@type": "String", "value": "A" }, "C"], [{ "@type": "String", "value": "B" }, "D"]] }, "listMultimapInterface": [[{ "@type": "String", "value": "A" }, "B"], [{ "@type": "String", "value": "A" }, "C"], [{ "@type": "String", "value": "B" }, "D"]], "setMultimapInterface": [[{ "@type": "String", "value": "A" }, "B"], [{ "@type": "String", "value": "A" }, "C"], [{ "@type": "String", "value": "B" }, "D"]], "multisetInterface": [], "sortedMultisetInterface": [], "listWildExtendsT": [], "listWildExtendsNumber": [], "listWildExtendsComparable": [], "setWildExtendsT": [], "setWildExtendsNumber": [], "setWildExtendsComparable": [], "listWildBuilder1": [], "listWildBuilder2": [], "mapWildBuilder1": {}, "mapWildKey": [], "table": [["A", 1, "B"], ["A", 2, "C"], ["B", 3, "D"]] } ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections1.packbinstr ================================================ arr (3) - int 3 - str 'org.joda.beans.sample.' - @type ImmGuava bean (35) - str 'collection' - str 'list' - str 'set' - str 'sortedSet' - str 'map' - str 'sortedMap' - str 'biMap' - str 'multimap' - str 'listMultimap' - str 'setMultimap' - str 'multiset' - str 'sortedMultiset' - str 'collectionInterface' - str 'listInterface' - str 'setInterface' - str 'sortedSetInterface' - str 'mapInterface' - str 'sortedMapInterface' - str 'biMapInterface' - str 'multimapInterface' - str 'listMultimapInterface' - str 'setMultimapInterface' - str 'multisetInterface' - str 'sortedMultisetInterface' - str 'listWildExtendsT' - str 'listWildExtendsNumber' - str 'listWildExtendsComparable' - str 'setWildExtendsT' - str 'setWildExtendsNumber' - str 'setWildExtendsComparable' - str 'listWildBuilder1' - str 'listWildBuilder2' - str 'mapWildBuilder1' - str 'mapWildKey' - str 'table' - arr (0) - arr (2) - str 'A' - str 'B' - arr (2) - str 'A' - str 'B' - arr (2) - str 'A' - str 'B' - map (2) = str 'A' str 'AA' = str 'B' str 'BB' - map (2) = str 'A' str 'AA' = str 'B' str 'BB' - map (2) = str 'A' str 'AA' = str 'B' str 'BB' - map (2) = str 'A' arr (2) - str 'B' - str 'C' = str 'B' arr (1) - str 'D' - map (2) = str 'A' arr (2) - str 'B' - str 'C' = str 'B' arr (1) - str 'D' - map (2) = str 'A' arr (2) - str 'B' - str 'C' = str 'B' arr (1) - str 'D' - map (3) = str 'A' int 1 = str 'B' int 2 = str 'C' int 3 - map (0) - arr (0) - arr (2) - str 'A' - str 'B' - arr (2) - str 'A' - str 'B' - arr (2) - str 'A' - str 'B' - map (2) = str 'A' str 'AA' = str 'B' str 'BB' - map (2) = str 'A' str 'AA' = str 'B' str 'BB' - map (2) = str 'A' str 'AA' = str 'B' str 'BB' - map (2) = str 'A' arr (2) - str 'B' - str 'C' = str 'B' arr (1) - str 'D' - map (2) = str 'A' arr (2) - str 'B' - str 'C' = str 'B' arr (1) - str 'D' - map (2) = str 'A' arr (2) - str 'B' - str 'C' = str 'B' arr (1) - str 'D' - map (0) - map (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - map (0) - map (0) - map (2) = str 'A' map (2) = int 1 str 'B' = int 2 str 'C' = str 'B' map (1) = int 3 str 'D' ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections1.refbinstr ================================================ arr (4) - int 2 - int 8 - map (2) = str 'String' arr (0) = str 'org.joda.beans.sample.ImmGuava' arr (35) - str 'collection' - str 'list' - str 'set' - str 'sortedSet' - str 'map' - str 'sortedMap' - str 'biMap' - str 'multimap' - str 'listMultimap' - str 'setMultimap' - str 'multiset' - str 'sortedMultiset' - str 'collectionInterface' - str 'listInterface' - str 'setInterface' - str 'sortedSetInterface' - str 'mapInterface' - str 'sortedMapInterface' - str 'biMapInterface' - str 'multimapInterface' - str 'listMultimapInterface' - str 'setMultimapInterface' - str 'multisetInterface' - str 'sortedMultisetInterface' - str 'listWildExtendsT' - str 'listWildExtendsNumber' - str 'listWildExtendsComparable' - str 'setWildExtendsT' - str 'setWildExtendsNumber' - str 'setWildExtendsComparable' - str 'listWildBuilder1' - str 'listWildBuilder2' - str 'mapWildBuilder1' - str 'mapWildKey' - str 'table' - arr (36) - ext type=32 '1' (bean) - map (1) = map (1) = ext type=35 '6' (refkey) ext type=34 'List' (meta) arr (0) - arr (2) - map (1) = ext type=33 '0' (data) map (1) = ext type=35 '0' (refkey) str 'A' - map (1) = ext type=33 '0' (data) map (1) = ext type=35 '1' (refkey) str 'B' - arr (2) - ext type=36 '0' (ref) - ext type=36 '1' (ref) - arr (2) - ext type=36 '0' (ref) - ext type=36 '1' (ref) - map (2) = ext type=36 '0' (ref) map (1) = ext type=35 '4' (refkey) str 'AA' = ext type=36 '1' (ref) map (1) = ext type=35 '5' (refkey) str 'BB' - map (2) = ext type=36 '0' (ref) ext type=36 '4' (ref) = ext type=36 '1' (ref) ext type=36 '5' (ref) - map (2) = ext type=36 '0' (ref) ext type=36 '4' (ref) = ext type=36 '1' (ref) ext type=36 '5' (ref) - map (1) = map (1) = ext type=35 '7' (refkey) ext type=34 'ListMultimap' (meta) map (3) = ext type=36 '0' (ref) ext type=36 '1' (ref) = ext type=36 '0' (ref) map (1) = ext type=35 '2' (refkey) str 'C' = ext type=36 '1' (ref) map (1) = ext type=35 '3' (refkey) str 'D' - map (3) = ext type=36 '0' (ref) ext type=36 '1' (ref) = ext type=36 '0' (ref) ext type=36 '2' (ref) = ext type=36 '1' (ref) ext type=36 '3' (ref) - map (3) = ext type=36 '0' (ref) ext type=36 '1' (ref) = ext type=36 '0' (ref) ext type=36 '2' (ref) = ext type=36 '1' (ref) ext type=36 '3' (ref) - map (3) = ext type=36 '0' (ref) int 1 = ext type=36 '1' (ref) int 2 = ext type=36 '2' (ref) int 3 - map (0) - map (1) = ext type=34 '6' (meta) arr (0) - arr (2) - ext type=36 '0' (ref) - ext type=36 '1' (ref) - arr (2) - ext type=36 '0' (ref) - ext type=36 '1' (ref) - arr (2) - ext type=36 '0' (ref) - ext type=36 '1' (ref) - map (2) = ext type=36 '0' (ref) ext type=36 '4' (ref) = ext type=36 '1' (ref) ext type=36 '5' (ref) - map (2) = ext type=36 '0' (ref) ext type=36 '4' (ref) = ext type=36 '1' (ref) ext type=36 '5' (ref) - map (2) = ext type=36 '0' (ref) ext type=36 '4' (ref) = ext type=36 '1' (ref) ext type=36 '5' (ref) - map (1) = ext type=34 '7' (meta) map (3) = ext type=36 '0' (ref) ext type=36 '1' (ref) = ext type=36 '0' (ref) ext type=36 '2' (ref) = ext type=36 '1' (ref) ext type=36 '3' (ref) - map (3) = ext type=36 '0' (ref) ext type=36 '1' (ref) = ext type=36 '0' (ref) ext type=36 '2' (ref) = ext type=36 '1' (ref) ext type=36 '3' (ref) - map (3) = ext type=36 '0' (ref) ext type=36 '1' (ref) = ext type=36 '0' (ref) ext type=36 '2' (ref) = ext type=36 '1' (ref) ext type=36 '3' (ref) - map (0) - map (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - arr (0) - map (0) - map (0) - arr (3) - arr (3) - ext type=36 '0' (ref) - int 1 - ext type=36 '1' (ref) - arr (3) - ext type=36 '0' (ref) - int 2 - ext type=36 '2' (ref) - arr (3) - ext type=36 '1' (ref) - int 3 - ext type=36 '3' (ref) ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections2.binstr ================================================ arr (2) - int 1 - map (36) = ext type=32 'org.joda.beans.sample.ImmGuava' (bean) nil = str 'collection' map (1) = ext type=34 'List' (meta) arr (0) = str 'list' arr (2) - str 'A' - str 'B' = str 'set' arr (2) - str 'A' - str 'B' = str 'sortedSet' arr (2) - str 'A' - str 'B' = str 'map' map (2) = str 'A' str 'AA' = str 'B' str 'BB' = str 'sortedMap' map (2) = str 'A' str 'AA' = str 'B' str 'BB' = str 'biMap' map (2) = str 'A' str 'AA' = str 'B' str 'BB' = str 'multimap' map (1) = ext type=34 'ListMultimap' (meta) map (3) = str 'A' str 'B' = str 'A' str 'C' = str 'B' str 'D' = str 'listMultimap' map (3) = str 'A' str 'B' = str 'A' str 'C' = str 'B' str 'D' = str 'setMultimap' map (3) = str 'A' str 'B' = str 'A' str 'C' = str 'B' str 'D' = str 'multiset' map (3) = str 'A' int 1 = str 'B' int 2 = str 'C' int 3 = str 'sortedMultiset' map (0) = str 'collectionInterface' map (1) = ext type=34 'List' (meta) arr (0) = str 'listInterface' arr (2) - str 'A' - str 'B' = str 'setInterface' arr (2) - str 'A' - str 'B' = str 'sortedSetInterface' arr (2) - str 'A' - str 'B' = str 'mapInterface' map (2) = str 'A' str 'AA' = str 'B' str 'BB' = str 'sortedMapInterface' map (2) = str 'A' str 'AA' = str 'B' str 'BB' = str 'biMapInterface' map (2) = str 'A' str 'AA' = str 'B' str 'BB' = str 'multimapInterface' map (1) = ext type=34 'ListMultimap' (meta) map (3) = str 'A' str 'B' = str 'A' str 'C' = str 'B' str 'D' = str 'listMultimapInterface' map (3) = str 'A' str 'B' = str 'A' str 'C' = str 'B' str 'D' = str 'setMultimapInterface' map (3) = str 'A' str 'B' = str 'A' str 'C' = str 'B' str 'D' = str 'multisetInterface' map (0) = str 'sortedMultisetInterface' map (0) = str 'listWildExtendsT' arr (0) = str 'listWildExtendsNumber' arr (0) = str 'listWildExtendsComparable' arr (0) = str 'setWildExtendsT' arr (0) = str 'setWildExtendsNumber' arr (0) = str 'setWildExtendsComparable' arr (0) = str 'listWildBuilder1' arr (0) = str 'listWildBuilder2' arr (0) = str 'mapWildBuilder1' map (0) = str 'mapWildKey' map (0) = str 'table' arr (3) - arr (3) - str 'A' - int 1 - str 'B' - arr (3) - str 'A' - int 2 - str 'C' - arr (3) - str 'B' - int 3 - str 'D' ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections2.json ================================================ { "@bean": "org.joda.beans.sample.ImmGuava", "collection": { "@meta": "List", "value": [] }, "list": ["A", "B"], "set": ["A", "B"], "sortedSet": ["A", "B"], "map": [["A", "AA"], ["B", "BB"]], "sortedMap": [["A", "AA"], ["B", "BB"]], "biMap": [["A", "AA"], ["B", "BB"]], "multimap": { "@meta": "ListMultimap", "value": [["A", "B"], ["A", "C"], ["B", "D"]] }, "listMultimap": [["A", "B"], ["A", "C"], ["B", "D"]], "setMultimap": [["A", "B"], ["A", "C"], ["B", "D"]], "multiset": [["A", 1], ["B", 2], ["C", 3]], "sortedMultiset": [], "collectionInterface": { "@meta": "List", "value": [] }, "listInterface": ["A", "B"], "setInterface": ["A", "B"], "sortedSetInterface": ["A", "B"], "mapInterface": [["A", "AA"], ["B", "BB"]], "sortedMapInterface": [["A", "AA"], ["B", "BB"]], "biMapInterface": [["A", "AA"], ["B", "BB"]], "multimapInterface": { "@meta": "ListMultimap", "value": [["A", "B"], ["A", "C"], ["B", "D"]] }, "listMultimapInterface": [["A", "B"], ["A", "C"], ["B", "D"]], "setMultimapInterface": [["A", "B"], ["A", "C"], ["B", "D"]], "multisetInterface": [], "sortedMultisetInterface": [], "listWildExtendsT": [], "listWildExtendsNumber": [], "listWildExtendsComparable": [], "setWildExtendsT": [], "setWildExtendsNumber": [], "setWildExtendsComparable": [], "listWildBuilder1": [], "listWildBuilder2": [], "mapWildBuilder1": {}, "mapWildKey": [], "table": [["A", 1, "B"], ["A", 2, "C"], ["B", 3, "D"]] } ================================================ FILE: src/test/resources/org/joda/beans/ser/Collections2.simplejson ================================================ { "collection": [], "list": ["A", "B"], "set": ["A", "B"], "sortedSet": ["A", "B"], "map": { "A": "AA", "B": "BB" }, "sortedMap": { "A": "AA", "B": "BB" }, "biMap": { "A": "AA", "B": "BB" }, "multimap": {}, "listMultimap": {}, "setMultimap": {}, "multiset": [["A", 1], ["B", 2], ["C", 3]], "sortedMultiset": [], "collectionInterface": [], "listInterface": ["A", "B"], "setInterface": ["A", "B"], "sortedSetInterface": ["A", "B"], "mapInterface": { "A": "AA", "B": "BB" }, "sortedMapInterface": { "A": "AA", "B": "BB" }, "biMapInterface": { "A": "AA", "B": "BB" }, "multimapInterface": {}, "listMultimapInterface": {}, "setMultimapInterface": {}, "multisetInterface": [], "sortedMultisetInterface": [], "listWildExtendsT": [], "listWildExtendsNumber": [], "listWildExtendsComparable": [], "setWildExtendsT": [], "setWildExtendsNumber": [], "setWildExtendsComparable": [], "listWildBuilder1": [], "listWildBuilder2": [], "mapWildBuilder1": {}, "mapWildKey": {}, "table": [] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress.xml ================================================ 185 Park Street London & Capital of the World <!> 89 a b c Etienne Colebourne 1 K T 0 A B a b c d 1 GBP 2 a b c Abba a b fr_CA 2 1 2 3 4 5.0 6.0 7 true d 1 e 2 B b 3 2 1 3 2 1 GBP Europe/London fr_CA 2 1 2 3 4 5.0 6.0 7 true Etiennette Colebourne 1 Kylie Colebourne 1 Hello There Etienne Colebourne 1 K T 0 A B Etiennette Colebourne 1 Kylie Colebourne 1 Kylie Colebourne 1 Etiennette Colebourne 1 Kylie Colebourne 1 Etiennette Colebourne 1 185 Park Street London QEFC Etiennette Colebourne 1 MEDIUM LOW LOW HIGH LOW MEDIUM 1.1,2.2,3.3 1.1,2.2 3.2 ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress1.binstr ================================================ arr (2) - int 1 - map (23) = ext type=32 'org.joda.beans.sample.ImmAddress' (bean) nil = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London & Capital of the World ' = str 'abstractNumber' map (1) = ext type=33 'Short' (data) int 89 = str 'array2d' map (1) = ext type=34 'String[][]' (meta) arr (3) - map (1) = ext type=34 'String[]' (meta) arr (1) - str 'a' - map (1) = ext type=34 'String[]' (meta) arr (0) - map (1) = ext type=34 'String[]' (meta) arr (2) - str 'b' - str 'c' = str 'owner' map (6) = str 'forename' str 'Etienne' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (2) - str 'K' - str 'T' = str 'addressList' arr (1) - map (1) = str 'number' int 0 = str 'codeCounts' map (2) = str 'A' int 2 = str 'B' int 1 = str 'object1' map (1) = ext type=34 'List' (meta) arr (3) - str 'a' - str 'b' - str 'c' = str 'object2' map (1) = ext type=34 'Map' (meta) map (2) = str 'd' int 1 = map (1) = ext type=33 'java.util.Currency' (data) str 'GBP' int 2 = str 'serializable' map (1) = ext type=34 'List' (meta) arr (3) - str 'a' - str 'b' - str 'c' = str 'objectInMap' map (4) = str 'A' str 'Abba' = str 'B' map (1) = ext type=34 'Set' (meta) arr (2) - str 'a' - str 'b' = str 'C' map (1) = ext type=34 'Set' (meta) arr (3) - map (1) = ext type=33 'Locale' (data) str 'fr_CA' - map (1) = ext type=33 'Long' (data) int 2 - map (9) = ext type=32 'PrimitiveBean' (bean) nil = str 'valueLong' int 1 = str 'valueInt' int 2 = str 'valueShort' int 3 = str 'valueByte' int 4 = str 'valueDouble' dbl 5.0 = str 'valueFloat' flt 6.0 = str 'valueChar' str '7' = str 'valueBoolean' true = str 'D' map (1) = ext type=34 'Map' (meta) map (2) = str 'd' int 1 = str 'e' int 2 = str 'listInMap' map (1) = str 'A' arr (2) - str 'B' - str 'b' = str 'listNumericInMap' map (1) = str 'A' arr (3) - int 3 - int 2 - int 1 = str 'listInListInMap' map (1) = str 'A' arr (1) - map (1) = ext type=34 'List' (meta) arr (3) - int 3 - int 2 - int 1 = str 'objectListInListInMap' map (2) = str 'A' arr (1) - map (1) = ext type=34 'List' (meta) arr (2) - map (1) = ext type=33 'Currency' (data) str 'GBP' - map (1) = ext type=33 'java.util.TimeZone' (data) str 'Europe/London' = str 'B' arr (1) - map (1) = ext type=34 'List' (meta) arr (3) - map (1) = ext type=33 'Locale' (data) str 'fr_CA' - map (1) = ext type=33 'Long' (data) int 2 - map (9) = ext type=32 'PrimitiveBean' (bean) nil = str 'valueLong' int 1 = str 'valueInt' int 2 = str 'valueShort' int 3 = str 'valueByte' int 4 = str 'valueDouble' dbl 5.0 = str 'valueFloat' flt 6.0 = str 'valueChar' str '7' = str 'valueBoolean' true = str 'mapInMap' map (1) = map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) map (1) = str 'sibling' map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'simpleTable' arr (2) - arr (3) - int 1 - int 1 - str 'Hello' - arr (3) - int 1 - int 2 - str 'There' = str 'compoundTable' arr (3) - arr (3) - int 1 - int 1 - map (6) = str 'forename' str 'Etienne' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (2) - str 'K' - str 'T' = str 'addressList' arr (1) - map (1) = str 'number' int 0 = str 'codeCounts' map (2) = str 'A' int 2 = str 'B' int 1 - arr (3) - int 1 - int 2 - map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) - arr (3) - int 2 - int 1 - map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'sparseGrid' arr (3) - int 5 - int 5 - arr (3) - int 1 - int 1 - map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'denseGrid' arr (8) - int 2 - int 3 - map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) - nil - nil - nil - map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) - nil = str 'beanBeanMap' map (1) = map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) map (17) = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London' = str 'data' bin '404142' = str 'owner' map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'object1' map (1) = ext type=33 'Risk' (data) str 'MEDIUM' = str 'object2' map (1) = ext type=33 'RiskPerception' (data) str 'LOW' = str 'risk' str 'LOW' = str 'riskLevel' str 'HIGH' = str 'riskLevels' arr (2) - str 'LOW' - str 'MEDIUM' = str 'objectInMap' map (0) = str 'listInMap' map (0) = str 'listNumericInMap' map (0) = str 'listInListInMap' map (0) = str 'objectListInListInMap' map (0) = str 'mapInMap' map (0) = str 'beanBeanMap' map (0) = str 'doubleVector' str '1.1,2.2,3.3' = str 'matrix' map (1) = ext type=34 'double[][]' (meta) arr (2) - str '1.1,2.2' - str '3.2' ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress1.json ================================================ { "@bean": "org.joda.beans.sample.ImmAddress", "number": 185, "street": "Park Street", "city": "London & Capital of the World \n", "abstractNumber": { "@type": "Short", "value": 89 }, "array2d": { "@meta": "String[][]", "value": [{ "@meta": "String[]", "value": ["a"] }, { "@meta": "String[]", "value": [] }, { "@meta": "String[]", "value": ["b", "c"] }] }, "owner": { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }, "object1": { "@meta": "List", "value": ["a", "b", "c"] }, "object2": { "@meta": "Map", "value": [["d", 1], [{ "@type": "java.util.Currency", "value": "GBP" }, 2]] }, "serializable": { "@meta": "List", "value": ["a", "b", "c"] }, "objectInMap": { "A": "Abba", "B": { "@meta": "Set", "value": ["a", "b"] }, "C": { "@meta": "Set", "value": [{ "@type": "Locale", "value": "fr_CA" }, { "@type": "Long", "value": 2 }, { "@bean": "PrimitiveBean", "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }] }, "D": { "@meta": "Map", "value": [["d", 1], ["e", 2]] } }, "listInMap": { "A": ["B", "b"] }, "listNumericInMap": { "A": [3, 2, 1] }, "listInListInMap": { "A": [{ "@meta": "List", "value": [3, 2, 1] }] }, "objectListInListInMap": { "A": [{ "@meta": "List", "value": [{ "@type": "Currency", "value": "GBP" }, { "@type": "java.util.TimeZone", "value": "Europe/London" }] }], "B": [{ "@meta": "List", "value": [{ "@type": "Locale", "value": "fr_CA" }, { "@type": "Long", "value": 2 }, { "@bean": "PrimitiveBean", "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }] }] }, "mapInMap": [[{ "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }, { "sibling": { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] } }]], "simpleTable": [[1, 1, "Hello"], [1, 2, "There"]], "compoundTable": [[1, 1, { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }], [1, 2, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [2, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "sparseGrid": [5, 5, [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "denseGrid": [2, 3, [0, 0, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "beanBeanMap": [[{ "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }, { "number": 185, "street": "Park Street", "city": "London", "data": "QEFC", "owner": { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }, "object1": { "@type": "Risk", "value": "MEDIUM" }, "object2": { "@type": "RiskPerception", "value": "LOW" }, "risk": "LOW", "riskLevel": "HIGH", "riskLevels": ["LOW", "MEDIUM"], "objectInMap": {}, "listInMap": {}, "listNumericInMap": {}, "listInListInMap": {}, "objectListInListInMap": {}, "mapInMap": [], "beanBeanMap": [] }]], "doubleVector": "1.1,2.2,3.3", "matrix": { "@meta": "double[][]", "value": ["1.1,2.2", "3.2"] } } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress1.packbinstr ================================================ arr (3) - int 3 - str 'org.joda.beans.sample.' - @type ImmAddress bean (26) - str 'number' - str 'street' - str 'city' - str 'abstractNumber' - str 'data' - str 'array2d' - str 'owner' - str 'object1' - str 'object2' - str 'risk' - str 'riskLevel' - str 'riskLevels' - str 'serializable' - str 'objectInMap' - str 'listInMap' - str 'listNumericInMap' - str 'listInListInMap' - str 'objectListInListInMap' - str 'mapInMap' - str 'simpleTable' - str 'compoundTable' - str 'sparseGrid' - str 'denseGrid' - str 'beanBeanMap' - str 'doubleVector' - str 'matrix' - int 185 - str 'Park Street' - str 'London & Capital of the World ' - sht 89 - null - arr (3) - arr (1) - str 'a' - arr (0) - arr (2) - str 'b' - str 'c' - @type ImmPerson bean (10) - str 'forename' - str 'surname' - str 'numberOfCars' - str 'dateOfBirth' - str 'middleNames' - str 'addressList' - str 'otherAddressMap' - str 'addressesList' - str 'mainAddress' - str 'codeCounts' - str 'Etienne' - str 'Colebourne' - int 1 - null - arr (2) - str 'K' - str 'T' - arr (1) - @type Address bean (4) - ref 1 'number' - ref 2 'street' - ref 3 'city' - ref 7 'owner' - int 0 - null - null - null - null - null - null - map (2) = str 'A' int 2 = str 'B' int 1 - @typeref List arr (3) - str 'a' - str 'b' - str 'c' - @typeref Map map (2) = str 'd' int 1 = @value @type java.util.Currency str 'GBP' int 2 - null - null - null - @typeref List arr (3) - str 'a' - str 'b' - str 'c' - map (4) = str 'A' str 'Abba' = str 'B' @typeref Set arr (2) - str 'a' - str 'b' = str 'C' @typeref Set arr (3) - @value @type Locale str 'fr_CA' - lng 2 - @type PrimitiveBean bean (8) - str 'valueLong' - str 'valueInt' - str 'valueShort' - str 'valueByte' - str 'valueDouble' - str 'valueFloat' - str 'valueChar' - str 'valueBoolean' - lng 1 - int 2 - sht 3 - byt 4 - dbl 5.0 - flt 6.0 - chr 7 - true = str 'D' @typeref Map map (2) = str 'd' int 1 = str 'e' int 2 - map (1) = str 'A' arr (2) - str 'B' - str 'b' - map (1) = str 'A' arr (3) - int 3 - int 2 - int 1 - map (1) = str 'A' arr (1) - arr (3) - int 3 - int 2 - int 1 - map (2) = str 'A' arr (1) - arr (2) - ref 42 'GBP' - @value @type java.util.TimeZone str 'Europe/London' = str 'B' arr (1) - arr (3) - ref 45 'fr_CA' - lng 2 - @typeref 5 PrimitiveBean arr (8) - lng 1 - int 2 - sht 3 - byt 4 - dbl 5.0 - flt 6.0 - chr 7 - true - map (1) = arr (10) - str 'Etiennette' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null map (1) = str 'sibling' arr (10) - str 'Kylie' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - map (1) = int 1 map (2) = int 1 str 'Hello' = int 2 str 'There' - map (2) = int 1 map (2) = int 1 arr (10) - ref 39 'Etienne' - ref 40 'Colebourne' - int 1 - null - arr (2) - str 'K' - str 'T' - arr (1) - arr (4) - int 0 - null - null - null - null - null - null - map (2) = str 'A' int 2 = str 'B' int 1 = int 2 arr (10) - ref 56 'Etiennette' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null = int 2 map (1) = int 1 arr (10) - ref 58 'Kylie' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - arr (3) - int 5 - int 5 - arr (3) - int 1 - int 1 - arr (10) - ref 58 'Kylie' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - arr (3) - int 2 - int 3 - arr (6) - int 0 - int 0 - arr (10) - ref 56 'Etiennette' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - int 1 - int 1 - arr (10) - ref 58 'Kylie' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - map (1) = arr (10) - ref 56 'Etiennette' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null arr (26) - int 185 - ref 27 'Park Street' - str 'London' - null - bin '404142' - null - arr (10) - ref 56 'Etiennette' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - @value @type Risk str 'MEDIUM' - @value @type RiskPerception str 'LOW' - @value @typeref 7 Risk ref 64 'LOW' - @value @typeref 7 Risk str 'HIGH' - arr (2) - ref 66 'LOW' - ref 63 'MEDIUM' - null - map (0) - map (0) - map (0) - map (0) - map (0) - map (0) - null - null - null - null - map (0) - null - null - dbl [1.1,2.2,3.3] - arr (2) - dbl [1.1,2.2] - dbl [3.2] ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress1.refbinstr ================================================ arr (4) - int 2 - int 17 - map (11) = str 'String' arr (0) = str 'org.joda.beans.sample.ImmAddress' arr (26) - str 'number' - str 'street' - str 'city' - str 'abstractNumber' - str 'data' - str 'array2d' - str 'owner' - str 'object1' - str 'object2' - str 'risk' - str 'riskLevel' - str 'riskLevels' - str 'serializable' - str 'objectInMap' - str 'listInMap' - str 'listNumericInMap' - str 'listInListInMap' - str 'objectListInListInMap' - str 'mapInMap' - str 'simpleTable' - str 'compoundTable' - str 'sparseGrid' - str 'denseGrid' - str 'beanBeanMap' - str 'doubleVector' - str 'matrix' = str 'Short' arr (0) = str 'org.joda.beans.sample.ImmPerson' arr (10) - str 'forename' - str 'surname' - str 'numberOfCars' - str 'dateOfBirth' - str 'middleNames' - str 'addressList' - str 'otherAddressMap' - str 'addressesList' - str 'mainAddress' - str 'codeCounts' = str 'java.util.Currency' arr (0) = str 'Integer' arr (0) = str 'Locale' arr (0) = str 'Long' arr (0) = str 'java.util.TimeZone' arr (0) = str 'org.joda.beans.sample.Risk' arr (0) = str 'org.joda.beans.sample.RiskPerception' arr (0) - arr (27) - ext type=32 '1' (bean) - int 185 - map (1) = ext type=35 '8' (refkey) str 'Park Street' - str 'London & Capital of the World ' - map (1) = ext type=33 '2' (data) int 89 - nil - map (1) = ext type=34 'String[][]' (meta) arr (3) - map (1) = ext type=34 'String[]' (meta) arr (1) - map (1) = ext type=35 '3' (refkey) str 'a' - map (1) = ext type=34 'String[]' (meta) arr (0) - map (1) = ext type=34 'String[]' (meta) arr (2) - map (1) = ext type=35 '1' (refkey) str 'b' - map (1) = ext type=35 '6' (refkey) str 'c' - map (1) = ext type=35 '9' (refkey) arr (10) - str 'Etienne' - map (1) = ext type=35 '7' (refkey) str 'Colebourne' - int 1 - nil - arr (2) - str 'K' - str 'T' - nil - nil - nil - nil - map (2) = map (1) = ext type=35 '0' (refkey) str 'A' int 2 = map (1) = ext type=35 '4' (refkey) str 'B' int 1 - map (1) = map (1) = ext type=35 '10' (refkey) ext type=34 'List' (meta) arr (3) - ext type=36 '3' (ref) - ext type=36 '1' (ref) - ext type=36 '6' (ref) - map (1) = ext type=34 'Map' (meta) map (2) = map (1) = ext type=35 '11' (refkey) str 'd' int 1 = map (1) = ext type=33 '4' (data) map (1) = ext type=35 '12' (refkey) str 'GBP' int 2 - nil - nil - nil - map (1) = ext type=34 '10' (meta) arr (3) - ext type=36 '3' (ref) - ext type=36 '1' (ref) - ext type=36 '6' (ref) - map (4) = ext type=36 '0' (ref) str 'Abba' = ext type=36 '4' (ref) map (1) = ext type=34 'Set' (meta) arr (2) - ext type=36 '3' (ref) - ext type=36 '1' (ref) = str 'C' map (1) = ext type=34 'Set' (meta) arr (2) - map (1) = ext type=33 '6' (data) map (1) = ext type=35 '13' (refkey) str 'fr_CA' - map (1) = ext type=33 '7' (data) int 2 = str 'D' map (1) = ext type=34 'Map' (meta) map (2) = ext type=36 '11' (ref) int 1 = str 'e' int 2 - map (1) = ext type=36 '0' (ref) arr (2) - ext type=36 '4' (ref) - ext type=36 '1' (ref) - map (1) = ext type=36 '0' (ref) arr (3) - int 3 - int 2 - int 1 - map (1) = ext type=36 '0' (ref) arr (1) - map (1) = ext type=34 '10' (meta) arr (3) - int 3 - int 2 - int 1 - map (2) = ext type=36 '0' (ref) arr (1) - map (1) = ext type=34 '10' (meta) arr (2) - ext type=36 '12' (ref) - map (1) = ext type=33 '8' (data) str 'Europe/London' = ext type=36 '4' (ref) arr (1) - map (1) = ext type=34 '10' (meta) arr (2) - ext type=36 '13' (ref) - map (1) = ext type=33 '7' (data) int 2 - map (1) = map (1) = ext type=35 '2' (refkey) arr (10) - str 'Etiennette' - ext type=36 '7' (ref) - int 1 - nil - arr (0) - nil - nil - nil - nil - nil map (1) = str 'sibling' map (1) = ext type=35 '5' (refkey) arr (10) - str 'Kylie' - ext type=36 '7' (ref) - int 1 - nil - arr (0) - nil - nil - nil - nil - nil - arr (2) - arr (3) - int 1 - int 1 - str 'Hello' - arr (3) - int 1 - int 2 - str 'There' - arr (3) - arr (3) - int 1 - int 1 - ext type=36 '9' (ref) - arr (3) - int 1 - int 2 - ext type=36 '2' (ref) - arr (3) - int 2 - int 1 - ext type=36 '5' (ref) - arr (3) - int 5 - int 5 - arr (3) - int 1 - int 1 - ext type=36 '5' (ref) - arr (8) - int 2 - int 3 - ext type=36 '2' (ref) - nil - nil - nil - ext type=36 '5' (ref) - nil - map (1) = ext type=36 '2' (ref) arr (26) - int 185 - ext type=36 '8' (ref) - str 'London' - nil - bin '404142' - nil - ext type=36 '2' (ref) - map (1) = ext type=33 '9' (data) map (1) = ext type=35 '15' (refkey) str 'MEDIUM' - map (1) = ext type=33 '10' (data) str 'LOW' - map (1) = ext type=35 '16' (refkey) str 'LOW' - str 'HIGH' - arr (2) - ext type=36 '16' (ref) - ext type=36 '15' (ref) - nil - map (0) - map (0) - map (0) - map (0) - map (0) - map (0) - nil - nil - nil - nil - map (0) - nil - nil - str '1.1,2.2,3.3' - map (1) = ext type=34 'double[][]' (meta) arr (2) - str '1.1,2.2' - str '3.2' ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress1.simplejson ================================================ { "number": 185, "street": "Park Street", "city": "London & Capital of the World \n", "abstractNumber": 89, "array2d": [["a"], [], ["b", "c"]], "owner": { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }, "object1": ["a", "b", "c"], "object2": { "d": 1, "GBP": 2 }, "serializable": ["a", "b", "c"], "objectInMap": { "A": "Abba", "B": ["a", "b"], "C": ["fr_CA", 2, { "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }], "D": { "d": 1, "e": 2 } }, "listInMap": { "A": ["B", "b"] }, "listNumericInMap": { "A": [3, 2, 1] }, "listInListInMap": { "A": [[3, 2, 1]] }, "objectListInListInMap": { "A": [["GBP", "Europe/London"]], "B": [["fr_CA", 2, { "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }]] }, "mapInMap": {}, "simpleTable": [[1, 1, "Hello"], [1, 2, "There"]], "compoundTable": [[1, 1, { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }], [1, 2, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [2, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "sparseGrid": [5, 5, [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "denseGrid": [2, 3, [0, 0, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "beanBeanMap": {}, "doubleVector": [1.1, 2.2, 3.3], "matrix": ["1.1,2.2", "3.2"] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress2.binstr ================================================ arr (2) - int 1 - map (23) = ext type=32 'org.joda.beans.sample.ImmAddress' (bean) nil = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London & Capital of the World ' = str 'abstractNumber' map (1) = ext type=33 'Short' (data) int 89 = str 'array2d' arr (3) - arr (1) - str 'a' - arr (0) - arr (2) - str 'b' - str 'c' = str 'owner' map (6) = str 'forename' str 'Etienne' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (2) - str 'K' - str 'T' = str 'addressList' arr (1) - map (1) = str 'number' int 0 = str 'codeCounts' map (2) = str 'A' int 2 = str 'B' int 1 = str 'object1' map (1) = ext type=34 'List' (meta) arr (3) - str 'a' - str 'b' - str 'c' = str 'object2' map (1) = ext type=34 'Map' (meta) map (2) = str 'd' int 1 = map (1) = ext type=33 'java.util.Currency' (data) str 'GBP' int 2 = str 'serializable' map (1) = ext type=34 'List' (meta) arr (3) - str 'a' - str 'b' - str 'c' = str 'objectInMap' map (4) = str 'A' str 'Abba' = str 'B' map (1) = ext type=34 'Set' (meta) arr (2) - str 'a' - str 'b' = str 'C' map (1) = ext type=34 'Set' (meta) arr (3) - map (1) = ext type=33 'Locale' (data) str 'fr_CA' - map (1) = ext type=33 'Long' (data) int 2 - map (9) = ext type=32 'PrimitiveBean' (bean) nil = str 'valueLong' int 1 = str 'valueInt' int 2 = str 'valueShort' int 3 = str 'valueByte' int 4 = str 'valueDouble' dbl 5.0 = str 'valueFloat' flt 6.0 = str 'valueChar' str '7' = str 'valueBoolean' true = str 'D' map (1) = ext type=34 'Map' (meta) map (2) = str 'd' int 1 = str 'e' int 2 = str 'listInMap' map (1) = str 'A' arr (2) - str 'B' - str 'b' = str 'listNumericInMap' map (1) = str 'A' arr (3) - int 3 - int 2 - int 1 = str 'listInListInMap' map (1) = str 'A' arr (1) - map (1) = ext type=34 'List' (meta) arr (3) - int 3 - int 2 - int 1 = str 'objectListInListInMap' map (2) = str 'A' arr (1) - map (1) = ext type=34 'List' (meta) arr (2) - map (1) = ext type=33 'Currency' (data) str 'GBP' - map (1) = ext type=33 'java.util.TimeZone' (data) str 'Europe/London' = str 'B' arr (1) - map (1) = ext type=34 'List' (meta) arr (3) - map (1) = ext type=33 'Locale' (data) str 'fr_CA' - map (1) = ext type=33 'Long' (data) int 2 - map (9) = ext type=32 'PrimitiveBean' (bean) nil = str 'valueLong' int 1 = str 'valueInt' int 2 = str 'valueShort' int 3 = str 'valueByte' int 4 = str 'valueDouble' dbl 5.0 = str 'valueFloat' flt 6.0 = str 'valueChar' str '7' = str 'valueBoolean' true = str 'mapInMap' map (1) = map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) map (1) = str 'sibling' map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'simpleTable' arr (2) - arr (3) - int 1 - int 1 - str 'Hello' - arr (3) - int 1 - int 2 - str 'There' = str 'compoundTable' arr (3) - arr (3) - int 1 - int 1 - map (6) = str 'forename' str 'Etienne' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (2) - str 'K' - str 'T' = str 'addressList' arr (1) - map (1) = str 'number' int 0 = str 'codeCounts' map (2) = str 'A' int 2 = str 'B' int 1 - arr (3) - int 1 - int 2 - map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) - arr (3) - int 2 - int 1 - map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'sparseGrid' arr (3) - int 5 - int 5 - arr (3) - int 1 - int 1 - map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'denseGrid' arr (8) - int 2 - int 3 - map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) - nil - nil - nil - map (4) = str 'forename' str 'Kylie' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) - nil = str 'beanBeanMap' map (1) = map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) map (17) = str 'number' int 185 = str 'street' str 'Park Street' = str 'city' str 'London' = str 'data' bin '404142' = str 'owner' map (4) = str 'forename' str 'Etiennette' = str 'surname' str 'Colebourne' = str 'numberOfCars' int 1 = str 'middleNames' arr (0) = str 'object1' map (1) = ext type=33 'Risk' (data) str 'MEDIUM' = str 'object2' map (1) = ext type=33 'RiskPerception' (data) str 'LOW' = str 'risk' str 'LOW' = str 'riskLevel' str 'HIGH' = str 'riskLevels' arr (2) - str 'LOW' - str 'MEDIUM' = str 'objectInMap' map (0) = str 'listInMap' map (0) = str 'listNumericInMap' map (0) = str 'listInListInMap' map (0) = str 'objectListInListInMap' map (0) = str 'mapInMap' map (0) = str 'beanBeanMap' map (0) = str 'doubleVector' arr (3) - dbl 1.1 - dbl 2.2 - dbl 3.3 = str 'matrix' arr (2) - arr (2) - dbl 1.1 - dbl 2.2 - arr (1) - dbl 3.2 ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress2.json ================================================ { "@bean": "org.joda.beans.sample.ImmAddress", "number": 185, "street": "Park Street", "city": "London & Capital of the World \n", "abstractNumber": { "@type": "Short", "value": 89 }, "array2d": [["a"], [], ["b", "c"]], "owner": { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }, "object1": { "@meta": "List", "value": ["a", "b", "c"] }, "object2": { "@meta": "Map", "value": [["d", 1], [{ "@type": "java.util.Currency", "value": "GBP" }, 2]] }, "serializable": { "@meta": "List", "value": ["a", "b", "c"] }, "objectInMap": { "A": "Abba", "B": { "@meta": "Set", "value": ["a", "b"] }, "C": { "@meta": "Set", "value": [{ "@type": "Locale", "value": "fr_CA" }, { "@type": "Long", "value": 2 }, { "@bean": "PrimitiveBean", "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }] }, "D": { "@meta": "Map", "value": [["d", 1], ["e", 2]] } }, "listInMap": { "A": ["B", "b"] }, "listNumericInMap": { "A": [3, 2, 1] }, "listInListInMap": { "A": [{ "@meta": "List", "value": [3, 2, 1] }] }, "objectListInListInMap": { "A": [{ "@meta": "List", "value": [{ "@type": "Currency", "value": "GBP" }, { "@type": "java.util.TimeZone", "value": "Europe/London" }] }], "B": [{ "@meta": "List", "value": [{ "@type": "Locale", "value": "fr_CA" }, { "@type": "Long", "value": 2 }, { "@bean": "PrimitiveBean", "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }] }] }, "mapInMap": [[{ "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }, { "sibling": { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] } }]], "simpleTable": [[1, 1, "Hello"], [1, 2, "There"]], "compoundTable": [[1, 1, { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }], [1, 2, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [2, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "sparseGrid": [5, 5, [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "denseGrid": [2, 3, [0, 0, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "beanBeanMap": [[{ "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }, { "number": 185, "street": "Park Street", "city": "London", "data": "QEFC", "owner": { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }, "object1": { "@type": "Risk", "value": "MEDIUM" }, "object2": { "@type": "RiskPerception", "value": "LOW" }, "risk": "LOW", "riskLevel": "HIGH", "riskLevels": ["LOW", "MEDIUM"], "objectInMap": {}, "listInMap": {}, "listNumericInMap": {}, "listInListInMap": {}, "objectListInListInMap": {}, "mapInMap": [], "beanBeanMap": [] }]], "doubleVector": [1.1, 2.2, 3.3], "matrix": [[1.1, 2.2], [3.2]] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddress2.simplejson ================================================ { "number": 185, "street": "Park Street", "city": "London & Capital of the World \n", "abstractNumber": 89, "array2d": [["a"], [], ["b", "c"]], "owner": { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }, "object1": ["a", "b", "c"], "object2": { "d": 1, "GBP": 2 }, "serializable": ["a", "b", "c"], "objectInMap": { "A": "Abba", "B": ["a", "b"], "C": ["fr_CA", 2, { "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }], "D": { "d": 1, "e": 2 } }, "listInMap": { "A": ["B", "b"] }, "listNumericInMap": { "A": [3, 2, 1] }, "listInListInMap": { "A": [[3, 2, 1]] }, "objectListInListInMap": { "A": [["GBP", "Europe/London"]], "B": [["fr_CA", 2, { "valueLong": 1, "valueInt": 2, "valueShort": 3, "valueByte": 4, "valueDouble": 5.0, "valueFloat": 6.0, "valueChar": "7", "valueBoolean": true }]] }, "mapInMap": {}, "simpleTable": [[1, 1, "Hello"], [1, 2, "There"]], "compoundTable": [[1, 1, { "forename": "Etienne", "surname": "Colebourne", "numberOfCars": 1, "middleNames": ["K", "T"], "addressList": [{ "number": 0 }], "codeCounts": [["A", 2], ["B", 1]] }], [1, 2, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [2, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "sparseGrid": [5, 5, [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "denseGrid": [2, 3, [0, 0, { "forename": "Etiennette", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }], [1, 1, { "forename": "Kylie", "surname": "Colebourne", "numberOfCars": 1, "middleNames": [] }]], "beanBeanMap": {}, "doubleVector": [1.1, 2.2, 3.3], "matrix": [[1.1, 2.2], [3.2]] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmAddressCached1.packbinstr ================================================ arr (3) - int 3 - str 'org.joda.beans.sample.' - @type ImmAddress bean (26) - str 'number' - str 'street' - str 'city' - str 'abstractNumber' - str 'data' - str 'array2d' - str 'owner' - str 'object1' - str 'object2' - str 'risk' - str 'riskLevel' - str 'riskLevels' - str 'serializable' - str 'objectInMap' - str 'listInMap' - str 'listNumericInMap' - str 'listInListInMap' - str 'objectListInListInMap' - str 'mapInMap' - str 'simpleTable' - str 'compoundTable' - str 'sparseGrid' - str 'denseGrid' - str 'beanBeanMap' - str 'doubleVector' - str 'matrix' - int 185 - str 'Park Street' - str 'London & Capital of the World ' - sht 89 - null - arr (3) - arr (1) - str 'a' - arr (0) - arr (2) - str 'b' - str 'c' - @value @type ImmPerson bean (10) - str 'forename' - str 'surname' - str 'numberOfCars' - str 'dateOfBirth' - str 'middleNames' - str 'addressList' - str 'otherAddressMap' - str 'addressesList' - str 'mainAddress' - str 'codeCounts' - str 'Etienne' - str 'Colebourne' - int 1 - null - arr (2) - str 'K' - str 'T' - arr (1) - @type Address bean (4) - ref 1 'number' - ref 2 'street' - ref 3 'city' - ref 7 'owner' - int 0 - null - null - null - null - null - null - map (2) = str 'A' int 2 = str 'B' int 1 - @typeref List arr (3) - str 'a' - str 'b' - str 'c' - @typeref Map map (2) = str 'd' int 1 = @value @type java.util.Currency str 'GBP' int 2 - null - null - null - @typeref List arr (3) - str 'a' - str 'b' - str 'c' - map (4) = str 'A' str 'Abba' = str 'B' @typeref Set arr (2) - str 'a' - str 'b' = str 'C' @typeref Set arr (3) - @value @type Locale str 'fr_CA' - lng 2 - @type PrimitiveBean bean (8) - str 'valueLong' - str 'valueInt' - str 'valueShort' - str 'valueByte' - str 'valueDouble' - str 'valueFloat' - str 'valueChar' - str 'valueBoolean' - lng 1 - int 2 - sht 3 - byt 4 - dbl 5.0 - flt 6.0 - chr 7 - true = str 'D' @typeref Map map (2) = str 'd' int 1 = str 'e' int 2 - map (1) = str 'A' arr (2) - str 'B' - str 'b' - map (1) = str 'A' arr (3) - int 3 - int 2 - int 1 - map (1) = str 'A' arr (1) - arr (3) - int 3 - int 2 - int 1 - map (2) = str 'A' arr (1) - arr (2) - ref 43 'GBP' - @value @type java.util.TimeZone str 'Europe/London' = str 'B' arr (1) - arr (3) - ref 46 'fr_CA' - lng 2 - @typeref 5 PrimitiveBean arr (8) - lng 1 - int 2 - sht 3 - byt 4 - dbl 5.0 - flt 6.0 - chr 7 - true - map (1) = @value @typeref 1 ImmPerson arr (10) - str 'Etiennette' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null map (1) = str 'sibling' @value @typeref 1 ImmPerson arr (10) - str 'Kylie' - ref 40 'Colebourne' - int 1 - null - arr (0) - null - null - null - null - null - map (1) = int 1 map (2) = int 1 str 'Hello' = int 2 str 'There' - map (2) = int 1 map (2) = int 1 ref 41 '' = int 2 ref 58 '' = int 2 map (1) = int 1 ref 61 '' - arr (3) - int 5 - int 5 - arr (3) - int 1 - int 1 - ref 61 '' - arr (3) - int 2 - int 3 - arr (6) - int 0 - int 0 - ref 58 '' - int 1 - int 1 - ref 61 '' - map (1) = ref 58 '' arr (26) - int 185 - ref 27 'Park Street' - str 'London' - null - bin '404142' - null - ref 58 '' - @value @type Risk str 'MEDIUM' - @value @type RiskPerception str 'LOW' - @value @typeref 7 Risk ref 67 'LOW' - @value @typeref 7 Risk str 'HIGH' - arr (2) - ref 69 'LOW' - ref 66 'MEDIUM' - null - map (0) - map (0) - map (0) - map (0) - map (0) - map (0) - null - null - null - null - map (0) - null - null - dbl [1.1,2.2,3.3] - arr (2) - dbl [1.1,2.2] - dbl [3.2] ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays1.binstr ================================================ arr (2) - int 1 - map (7) = ext type=32 'org.joda.beans.sample.ImmArrays' (bean) nil = str 'intArray' str '1,3,2' = str 'longArray' str '1,4,3' = str 'doubleArray' str '1.1,2.2,3.3' = str 'booleanArray' str 'TF' = str 'intArray2d' map (1) = ext type=34 'int[][]' (meta) arr (3) - str '1,2' - str '2' - str '' = str 'booleanArray2d' map (1) = ext type=34 'boolean[][]' (meta) arr (3) - str 'TF' - str 'F' - str '' ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays1.json ================================================ { "@bean": "org.joda.beans.sample.ImmArrays", "intArray": "1,3,2", "longArray": "1,4,3", "doubleArray": "1.1,2.2,3.3", "booleanArray": "TF", "intArray2d": { "@meta": "int[][]", "value": ["1,2", "2", ""] }, "booleanArray2d": { "@meta": "boolean[][]", "value": ["TF", "F", ""] } } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays1.packbinstr ================================================ arr (3) - int 3 - str 'org.joda.beans.sample.' - @type ImmArrays bean (6) - str 'intArray' - str 'longArray' - str 'doubleArray' - str 'booleanArray' - str 'intArray2d' - str 'booleanArray2d' - arr (3) - int 1 - int 3 - int 2 - arr (3) - lng 1 - lng 4 - lng 3 - dbl [1.1,2.2,3.3] - arr (2) - true - false - arr (3) - arr (2) - int 1 - int 2 - arr (1) - int 2 - arr (0) - arr (3) - arr (2) - true - false - arr (1) - false - arr (0) ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays1.refbinstr ================================================ arr (4) - int 2 - int 0 - map (1) = str 'org.joda.beans.sample.ImmArrays' arr (6) - str 'intArray' - str 'longArray' - str 'doubleArray' - str 'booleanArray' - str 'intArray2d' - str 'booleanArray2d' - arr (7) - ext type=32 '0' (bean) - str '1,3,2' - str '1,4,3' - str '1.1,2.2,3.3' - str 'TF' - map (1) = ext type=34 'int[][]' (meta) arr (3) - str '1,2' - str '2' - str '' - map (1) = ext type=34 'boolean[][]' (meta) arr (3) - str 'TF' - str 'F' - str '' ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays1.simplejson ================================================ { "intArray": [1, 3, 2], "longArray": [1, 4, 3], "doubleArray": [1.1, 2.2, 3.3], "booleanArray": [true, false], "intArray2d": ["1,2", "2", ""], "booleanArray2d": ["TF", "F", ""] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays2.binstr ================================================ arr (2) - int 1 - map (7) = ext type=32 'org.joda.beans.sample.ImmArrays' (bean) nil = str 'intArray' arr (3) - int 1 - int 3 - int 2 = str 'longArray' arr (3) - int 1 - int 4 - int 3 = str 'doubleArray' arr (3) - dbl 1.1 - dbl 2.2 - dbl 3.3 = str 'booleanArray' arr (2) - true - false = str 'intArray2d' arr (3) - arr (2) - int 1 - int 2 - arr (1) - int 2 - arr (0) = str 'booleanArray2d' arr (3) - arr (2) - true - false - arr (1) - false - arr (0) ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays2.json ================================================ { "@bean": "org.joda.beans.sample.ImmArrays", "intArray": [1, 3, 2], "longArray": [1, 4, 3], "doubleArray": [1.1, 2.2, 3.3], "booleanArray": [true, false], "intArray2d": [[1, 2], [2], []], "booleanArray2d": [[true, false], [false], []] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmArrays2.simplejson ================================================ { "intArray": [1, 3, 2], "longArray": [1, 4, 3], "doubleArray": [1.1, 2.2, 3.3], "booleanArray": [true, false], "intArray2d": [[1, 2], [2], []], "booleanArray2d": [[true, false], [false], []] } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmOptional.xml ================================================ A 12 ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmOptional1.packbinstr ================================================ arr (3) - int 3 - str 'org.joda.beans.sample.' - @type ImmOptional bean (7) - str 'optString' - str 'optStringEmpty' - str 'optStringGetter' - str 'optLongGetter' - str 'optIntGetter' - str 'optDoubleGetter' - str 'twelve' - arr (1) - str 'A' - arr (0) - null - null - null - null - int 12 ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmOptional1.refbinstr ================================================ arr (4) - int 2 - int 0 - map (1) = str 'org.joda.beans.sample.ImmOptional' arr (6) - str 'optString' - str 'optStringEmpty' - str 'optStringGetter' - str 'optLongGetter' - str 'optIntGetter' - str 'optDoubleGetter' - arr (7) - ext type=32 '0' (bean) - str 'A' - nil - nil - nil - nil - nil ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmOptional2.binstr ================================================ arr (2) - int 1 - map (3) = ext type=32 'org.joda.beans.sample.ImmOptional' (bean) nil = str 'optString' str 'A' = str 'twelve' int 12 ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmOptional2.json ================================================ { "@bean": "org.joda.beans.sample.ImmOptional", "optString": "A", "twelve": 12 } ================================================ FILE: src/test/resources/org/joda/beans/ser/ImmOptional2.simplejson ================================================ { "optString": "A", "twelve": 12 } ================================================ FILE: src/test/resources/org/joda/beans/ser/SimpleJson2.simplejson ================================================ { "primitiveChar": "a", "primitiveByte": 23, "primitiveShort": 12, "primitiveInt": 9, "primitiveLong": 6, "primitiveFloat": 3.4, "primitiveDouble": 2.3, "primitiveDoubleNaN": null, "primitiveDoubleInf": "Infinity", "abstractNumber": 29, "arrayByte": "QEFC", "array2d": [["a"], [], ["b", "c"]], "string": "ABBA", "bean": { "name": "Cat" }, "object1": ["a", "b", "c"], "object2": { "d": 1, "12": "2" }, "risk": "LOW", "riskLevel": "HIGH", "riskLevels": ["LOW", "MEDIUM"], "stringList": ["a", "b", "c"], "beanList": [{ "name": "Cat" }, { "name": "Dog" }], "stringMap": { "a": "A", "b": "B" }, "intKeyMap": { "1": "A", "2": "B" }, "beanMap": { "a": { "name": "Cat" }, "b": { "name": "Dog" } }, "listInMap": { "A": ["B", "b"] }, "listNumericInMap": { "A": [3, 2, 1] }, "objectInMap": { "a": 2147483648 } }