├── accounting ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── softwarearchetypes │ │ └── accounting │ │ ├── AccountMetadataView.java │ │ ├── TransactionAccountEntriesView.java │ │ ├── events │ │ ├── AccountingEvent.java │ │ ├── DebitEntryRegistered.java │ │ └── CreditEntryRegistered.java │ │ ├── postingrules │ │ ├── PostingCalculator.java │ │ ├── PostingRuleRepository.java │ │ ├── PostingRule.java │ │ ├── PostingRuleId.java │ │ ├── BusinessContext.java │ │ ├── TargetAccounts.java │ │ ├── InMemoryPostingRuleRepository.java │ │ ├── AccountFinder.java │ │ └── PostingContext.java │ │ ├── EntryId.java │ │ ├── GroupId.java │ │ ├── TransactionView.java │ │ ├── ReverseTransactionCommand.java │ │ ├── AccountId.java │ │ ├── TransactionId.java │ │ ├── CreateAccount.java │ │ ├── TransactionRepository.java │ │ ├── Balances.java │ │ ├── MetaData.java │ │ ├── AccountView.java │ │ ├── TransactionType.java │ │ ├── TransactionBuilderFactory.java │ │ ├── AccountName.java │ │ ├── EntryView.java │ │ ├── ProjectionAccount.java │ │ ├── Validity.java │ │ ├── ExecuteTransactionCommand.java │ │ └── Entries.java ├── .gitattributes ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties └── .gitignore ├── configurator ├── src │ ├── test │ │ └── resources │ │ │ ├── 1Variable_2Clauses_UNSAT.txt │ │ │ ├── 2Variables_3Clauses_SAT.txt │ │ │ ├── 3Variables_8Clauses_UNSAT.txt │ │ │ ├── 12Variables_36Clauses_SAT2.txt │ │ │ ├── 12Variables_36Clauses_SAT.txt │ │ │ ├── 12Variables_36Clauses_UNSAT.txt │ │ │ └── 23Variables_75Clauses_SAT.txt │ └── main │ │ └── java │ │ └── softwarearchetypes │ │ ├── carconfig │ │ ├── Rule.java │ │ ├── CarConfigId.java │ │ ├── CarConfigProcessId.java │ │ ├── CarConfigurationProcessRepository.java │ │ └── OptionsRepository.java │ │ └── sat │ │ └── Clause.java └── pom.xml ├── product ├── .gitattributes ├── src │ ├── main │ │ ├── resources │ │ │ └── application.properties │ │ └── java │ │ │ └── com │ │ │ └── softwarearchetypes │ │ │ └── product │ │ │ ├── ProductIdentifier.java │ │ │ ├── ProductApplication.java │ │ │ ├── SerialNumber.java │ │ │ ├── BatchId.java │ │ │ ├── ProductName.java │ │ │ ├── ProductDescription.java │ │ │ ├── BatchName.java │ │ │ ├── UuidProductIdentifier.java │ │ │ ├── ProductInstanceId.java │ │ │ ├── TextualSerialNumber.java │ │ │ ├── Unconstrained.java │ │ │ ├── ServiceDeliveryStatus.java │ │ │ ├── ProductFeatureTypeDefinition.java │ │ │ ├── VinSerialNumber.java │ │ │ ├── CatalogEntryId.java │ │ │ ├── RegexConstraint.java │ │ │ └── NumericRangeConstraint.java │ └── test │ │ └── java │ │ └── com │ │ └── softwarearchetypes │ │ └── product │ │ └── ProductApplicationTests.java ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties └── .gitignore ├── quantity ├── .gitattributes ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── .gitignore └── src │ └── main │ └── java │ └── com │ └── softwarearchetypes │ └── quantity │ └── Unit.java ├── party ├── src │ ├── main │ │ ├── resources │ │ │ └── application.properties │ │ └── java │ │ │ └── com │ │ │ └── softwarearchetypes │ │ │ ├── common │ │ │ ├── Pair.java │ │ │ ├── StringUtils.java │ │ │ ├── Version.java │ │ │ └── Preconditions.java │ │ │ └── party │ │ │ ├── AddressDetails.java │ │ │ ├── events │ │ │ ├── PublishedEvent.java │ │ │ ├── PartyRelatedEvent.java │ │ │ ├── AddressRelatedEvent.java │ │ │ ├── AddressRemovalFailed.java │ │ │ ├── PartyRelatedFailureEvent.java │ │ │ ├── PersonalDataUpdateFailed.java │ │ │ ├── PartyNotFound.java │ │ │ ├── PersonalDataUpdateSucceeded.java │ │ │ ├── OrganizationNameUpdateFailed.java │ │ │ ├── OrganizationNameUpdateSucceeded.java │ │ │ ├── RoleAdded.java │ │ │ ├── RoleRemoved.java │ │ │ ├── RoleAdditionFailed.java │ │ │ ├── RoleRemovalFailed.java │ │ │ ├── AddressDefinitionSucceeded.java │ │ │ ├── RoleAdditionSucceeded.java │ │ │ ├── RoleRemovalSucceeded.java │ │ │ ├── GeoAddressRemoved.java │ │ │ ├── PartyRelationshipRemoved.java │ │ │ ├── AddressUpdateSucceeded.java │ │ │ ├── IncorrectPartyTypeIdentified.java │ │ │ ├── AddressDefinitionFailed.java │ │ │ ├── AddressRemovalSucceeded.java │ │ │ ├── OrganizationNameUpdated.java │ │ │ ├── PersonalDataUpdated.java │ │ │ ├── RegisteredIdentifierAdditionFailed.java │ │ │ ├── RegisteredIdentifierRemovalFailed.java │ │ │ ├── PartyRegistered.java │ │ │ ├── RegisteredIdentifierAdded.java │ │ │ ├── RegisteredIdentifierRemoved.java │ │ │ ├── EventPublisher.java │ │ │ ├── RegisteredIdentifierAdditionSucceeded.java │ │ │ ├── RegisteredIdentifierRemovalSucceeded.java │ │ │ ├── CompanyRegistered.java │ │ │ ├── OrganizationUnitRegistered.java │ │ │ ├── PersonRegistered.java │ │ │ ├── PartyRegistrationFailed.java │ │ │ ├── DomainEvent.java │ │ │ ├── PartyRelationshipAdded.java │ │ │ ├── AddressUpdateFailed.java │ │ │ ├── PartyRoleDefinitionFailed.java │ │ │ ├── RoleAdditionSkipped.java │ │ │ ├── RoleRemovalSkipped.java │ │ │ ├── AddressAdditionFailed.java │ │ │ ├── AddressRemovalSkipped.java │ │ │ ├── AddressUpdateSkipped.java │ │ │ ├── OrganizationNameUpdateSkipped.java │ │ │ ├── RegisteredIdentifierAdditionSkipped.java │ │ │ ├── PersonalDataUpdateSkipped.java │ │ │ ├── RegisteredIdentifierRemovalSkipped.java │ │ │ ├── PartyRelationshipDefinitionFailed.java │ │ │ ├── GeoAddressUpdated.java │ │ │ ├── GeoAddressDefined.java │ │ │ └── InMemoryEventsPublisher.java │ │ │ ├── PartyAuthenticationService.java │ │ │ ├── AddressUseType.java │ │ │ ├── RegisteredIdentifier.java │ │ │ ├── ZipCode.java │ │ │ ├── OrganizationName.java │ │ │ ├── Address.java │ │ │ ├── PartyApplication.java │ │ │ ├── AddressesRepository.java │ │ │ ├── PartyRoleDefiningPolicy.java │ │ │ ├── AddressDefiningPolicy.java │ │ │ ├── PartyRelationshipDefiningPolicy.java │ │ │ ├── Role.java │ │ │ ├── AddressLifecycle.java │ │ │ ├── PartyRepository.java │ │ │ ├── RelationshipName.java │ │ │ ├── AddressId.java │ │ │ ├── PersonalData.java │ │ │ ├── PartyId.java │ │ │ ├── AddressesQueries.java │ │ │ ├── PartyRelationshipId.java │ │ │ ├── PartyRelationship.java │ │ │ ├── PartyRelationshipRepository.java │ │ │ ├── PartyRole.java │ │ │ ├── Company.java │ │ │ ├── OrganizationUnit.java │ │ │ ├── PersonalIdentificationNumber.java │ │ │ ├── PartyRoleFactory.java │ │ │ ├── InMemoryAddressesRepository.java │ │ │ ├── PartiesQueries.java │ │ │ ├── Organization.java │ │ │ ├── InMemoryPartyRepository.java │ │ │ └── PartyRelationshipsQueries.java │ └── test │ │ └── java │ │ └── com │ │ └── softwarearchetypes │ │ ├── party │ │ ├── PersonRolesTest.java │ │ ├── CompanyRolesTest.java │ │ ├── OrganizationUnitRolesTest.java │ │ ├── PersonRegisteredIdentifiersTest.java │ │ ├── CompanyRegisteredIdentifiersTest.java │ │ ├── OrganizationUnitRegisteredIdentifiersTest.java │ │ ├── OrganizationNameFixture.java │ │ ├── AddressesTestSupport.java │ │ ├── RelationshipNameFixture.java │ │ ├── TestPartyApplication.java │ │ ├── PartyRelationshipTestSupport.java │ │ ├── PersonTestDataBuilder.java │ │ ├── CompanyTestDataBuilder.java │ │ ├── OrganizationUnitTestDataBuilder.java │ │ ├── PersonalDataFixture.java │ │ ├── PartyRelationshipFixture.java │ │ ├── RoleFixture.java │ │ ├── PartiesTestEventListener.java │ │ ├── RegisteredIdentifierFixture.java │ │ ├── PartyIdTest.java │ │ ├── AddressIdTest.java │ │ ├── PartyAbstractTestDataBuilder.java │ │ └── RoleTest.java │ │ └── common │ │ ├── CollectionFixture.java │ │ └── RandomFixture.java ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── diagrams │ ├── party-basic-model.png │ ├── party-sample-graph.jpg │ ├── party-addresses-model.png │ ├── party-relationship-model.png │ ├── party-sample-graph-path.jpg │ ├── party-with-data-and-auth.png │ ├── party-addresses-aggregate-model.png │ ├── party-relationship-model.puml │ ├── party-basic-model.puml │ ├── party-addresses-model.puml │ └── party-addresses-aggregate-model.puml └── .gitignore ├── waitlist ├── src │ ├── main │ │ ├── resources │ │ │ └── application.properties │ │ └── java │ │ │ └── com │ │ │ └── softwarearchetypes │ │ │ └── waitlist │ │ │ ├── WaitListType.java │ │ │ ├── WaitListId.java │ │ │ ├── WaitListApplication.java │ │ │ ├── WaitListRepository.java │ │ │ ├── Element.java │ │ │ └── InMemoryWaitListRepository.java │ └── test │ │ └── groovy │ │ └── com │ │ └── softwarearchetypes │ │ └── waitlist │ │ └── WaitListFixture.groovy └── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── availability ├── timed-availability │ ├── src │ │ ├── test │ │ │ ├── resources │ │ │ │ └── application.properties │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── softwarearchetypes │ │ │ │ ├── MockedClockConfiguration.java │ │ │ │ ├── MockedEventPublisherConfiguration.java │ │ │ │ └── TestDbConfiguration.java │ │ └── main │ │ │ ├── resources │ │ │ ├── application.properties │ │ │ └── schema-availability.sql │ │ │ └── java │ │ │ └── com │ │ │ └── softwarearchetypes │ │ │ ├── availability │ │ │ ├── EventsPublisher.java │ │ │ ├── PublishedEvent.java │ │ │ ├── ResourceTakenOver.java │ │ │ ├── Owner.java │ │ │ ├── ResourceAvailabilityId.java │ │ │ ├── AvailabilityConfiguration.java │ │ │ ├── Blockade.java │ │ │ ├── segment │ │ │ │ ├── Segments.java │ │ │ │ └── SegmentInMinutes.java │ │ │ ├── Calendars.java │ │ │ ├── Calendar.java │ │ │ └── ResourceId.java │ │ │ ├── ClockConfiguration.java │ │ │ └── AvailabilityApplication.java │ ├── images │ │ ├── calendar-all.png │ │ ├── calendar-day-view.png │ │ ├── calendar-month-john-smith.png │ │ ├── segmentation-locking-point.png │ │ ├── timerange-overlapping-locking-point.png │ │ └── timerange-overlapping-without-conflict.png │ └── diagrams │ │ ├── car-with-booleans.png │ │ ├── calendar-per-resource.png │ │ ├── car-availability-distributed.png │ │ ├── availability-facade-introduced.png │ │ ├── resource-availability-final-version.png │ │ ├── calendar-per-resource-per-time-period.png │ │ ├── car-with-booleans.puml │ │ ├── calendar-per-resource.puml │ │ └── calendar-per-resource-per-time-period.puml └── simple-availability │ └── src │ ├── test │ ├── resources │ │ ├── application-integrationTest.yml │ │ └── testContainers │ │ │ └── postgresContainer.sql │ └── groovy │ │ └── com │ │ └── softwarearchetypes │ │ └── availability │ │ ├── RandomUtils.groovy │ │ ├── domain │ │ ├── OwnerIdFixture.groovy │ │ ├── AssetIdFixture.groovy │ │ └── DurationFixture.groovy │ │ ├── application │ │ ├── InMemoryDomainEventPublisher.groovy │ │ └── InMemoryAssetAvailabilityRepository.groovy │ │ └── PredefinedPollingConditions.groovy │ └── main │ ├── java │ └── com │ │ └── softwarearchetypes │ │ └── availability │ │ ├── events │ │ ├── DomainEventsPublisher.java │ │ ├── BaseDomainEvent.java │ │ ├── AssetWithdrawn.java │ │ ├── AssetLockExpired.java │ │ ├── AssetRegistered.java │ │ ├── AssetRegistrationRejected.java │ │ ├── AssetActivated.java │ │ └── AssetActivationRejected.java │ │ ├── commands │ │ ├── Unlock.java │ │ ├── Activate.java │ │ ├── Register.java │ │ ├── Withdraw.java │ │ ├── Lock.java │ │ ├── LockIndefinitely.java │ │ └── Command.java │ │ ├── domain │ │ ├── AssetId.java │ │ ├── OwnerId.java │ │ └── AssetAvailabilityRepository.java │ │ ├── AvailabilityApplication.java │ │ ├── infrastructure │ │ └── events │ │ │ └── SpringEventPublisher.java │ │ └── application │ │ └── OverdueLockHandling.java │ └── resources │ ├── db │ └── changelog │ │ ├── db.changelog-202201081200-grant-schema-privileges.yaml │ │ ├── db.changelog-202201081202-grant-asset-availability-privileges.yaml │ │ ├── db.changelog-master.yaml │ │ └── db.changelog-202201081201-create-asset-availability-table.yaml │ └── application.yml ├── common └── src │ └── main │ └── java │ └── com │ └── softwarearchetypes │ └── common │ ├── Pair.java │ ├── StringUtils.java │ ├── events │ ├── EventHandler.java │ ├── PublishedEvent.java │ ├── EventPublisher.java │ └── InMemoryEventsPublisher.java │ ├── Version.java │ └── Preconditions.java ├── general-assignment ├── src │ └── main │ │ └── java │ │ └── softwarearchetypes │ │ └── multidimensionalknapsack │ │ ├── CapacityDimension.java │ │ ├── WeightDimension.java │ │ ├── Item.java │ │ ├── Result.java │ │ ├── TotalWeight.java │ │ └── TotalCapacity.java └── pom.xml ├── pricing └── src │ └── main │ └── java │ └── com │ └── softwarearchetypes │ └── pricing │ ├── CalculatorView.java │ ├── CalculatorId.java │ └── CalculatorType.java ├── .gitignore ├── README.md └── pom.xml /accounting/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /configurator/src/test/resources/1Variable_2Clauses_UNSAT.txt: -------------------------------------------------------------------------------- 1 | 1 2 | -1 -------------------------------------------------------------------------------- /product/.gitattributes: -------------------------------------------------------------------------------- 1 | /mvnw text eol=lf 2 | *.cmd text eol=crlf 3 | -------------------------------------------------------------------------------- /accounting/.gitattributes: -------------------------------------------------------------------------------- 1 | /mvnw text eol=lf 2 | *.cmd text eol=crlf 3 | -------------------------------------------------------------------------------- /quantity/.gitattributes: -------------------------------------------------------------------------------- 1 | /mvnw text eol=lf 2 | *.cmd text eol=crlf 3 | -------------------------------------------------------------------------------- /configurator/src/test/resources/2Variables_3Clauses_SAT.txt: -------------------------------------------------------------------------------- 1 | 1 2 2 | -1 2 3 | 1 -2 -------------------------------------------------------------------------------- /party/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=party 2 | -------------------------------------------------------------------------------- /product/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=product 2 | -------------------------------------------------------------------------------- /waitlist/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=waitList 2 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /party/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /party/diagrams/party-basic-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-basic-model.png -------------------------------------------------------------------------------- /party/diagrams/party-sample-graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-sample-graph.jpg -------------------------------------------------------------------------------- /availability/timed-availability/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.hikari.data-source-properties.reWriteBatchedInserts=true -------------------------------------------------------------------------------- /party/diagrams/party-addresses-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-addresses-model.png -------------------------------------------------------------------------------- /configurator/src/test/resources/3Variables_8Clauses_UNSAT.txt: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | 1 2 -3 3 | 1 -2 3 4 | 1 -2 -3 5 | -1 2 3 6 | -1 2 -3 7 | -1 -2 3 8 | -1 -2 -3 -------------------------------------------------------------------------------- /party/diagrams/party-relationship-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-relationship-model.png -------------------------------------------------------------------------------- /party/diagrams/party-sample-graph-path.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-sample-graph-path.jpg -------------------------------------------------------------------------------- /party/diagrams/party-with-data-and-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-with-data-and-auth.png -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/Pair.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public record Pair(T first, T second) { 4 | 5 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/common/Pair.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public record Pair(T first, T second) { 4 | 5 | } -------------------------------------------------------------------------------- /party/diagrams/party-addresses-aggregate-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/party/diagrams/party-addresses-aggregate-model.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressDetails.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | public interface AddressDetails { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /availability/timed-availability/images/calendar-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/images/calendar-all.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PublishedEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /waitlist/src/main/java/com/softwarearchetypes/waitlist/WaitListType.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist; 2 | 3 | enum WaitListType { 4 | FIFO, PRIORITIZED 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRelatedEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /availability/timed-availability/images/calendar-day-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/images/calendar-day-view.png -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/car-with-booleans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/diagrams/car-with-booleans.png -------------------------------------------------------------------------------- /availability/timed-availability/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.sql.init.mode=always 2 | spring.datasource.hikari.data-source-properties.reWriteBatchedInserts=true 3 | 4 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/calendar-per-resource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/diagrams/calendar-per-resource.png -------------------------------------------------------------------------------- /availability/timed-availability/images/calendar-month-john-smith.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/images/calendar-month-john-smith.png -------------------------------------------------------------------------------- /availability/simple-availability/src/test/resources/application-integrationTest.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | kafka: 3 | consumer: 4 | group-id: test-listener-${random.uuid} 5 | auto-offset-reset: latest -------------------------------------------------------------------------------- /availability/timed-availability/images/segmentation-locking-point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/images/segmentation-locking-point.png -------------------------------------------------------------------------------- /general-assignment/src/main/java/softwarearchetypes/multidimensionalknapsack/CapacityDimension.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.multidimensionalknapsack; 2 | 3 | public interface CapacityDimension { 4 | } 5 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/car-availability-distributed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/diagrams/car-availability-distributed.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressRelatedEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface AddressRelatedEvent extends PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/availability-facade-introduced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/diagrams/availability-facade-introduced.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressRemovalFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface AddressRemovalFailed extends AddressRelatedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/AccountMetadataView.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | public record AccountMetadataView(AccountId id, String name, String type) { 4 | 5 | } -------------------------------------------------------------------------------- /availability/timed-availability/images/timerange-overlapping-locking-point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/images/timerange-overlapping-locking-point.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRelatedFailureEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface PartyRelatedFailureEvent extends PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PersonalDataUpdateFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PersonalDataUpdateFailed() implements PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ProductIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | public interface ProductIdentifier { 4 | 5 | String type(); 6 | String toString(); 7 | } -------------------------------------------------------------------------------- /accounting/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=only-script 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/resource-availability-final-version.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/diagrams/resource-availability-final-version.png -------------------------------------------------------------------------------- /availability/timed-availability/images/timerange-overlapping-without-conflict.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/images/timerange-overlapping-without-conflict.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyNotFound.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PartyNotFound(String partyId) implements PartyRelatedFailureEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PersonalDataUpdateSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface PersonalDataUpdateSucceeded extends PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /product/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=only-script 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | -------------------------------------------------------------------------------- /quantity/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=only-script 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip 4 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/calendar-per-resource-per-time-period.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Software-Archetypes/archetypes/HEAD/availability/timed-availability/diagrams/calendar-per-resource-per-time-period.png -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/OrganizationNameUpdateFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record OrganizationNameUpdateFailed() implements PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/OrganizationNameUpdateSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public interface OrganizationNameUpdateSucceeded extends PartyRelatedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyAuthenticationService.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class PartyAuthenticationService { 4 | 5 | //authenticate 6 | //-> show auth policies here 7 | } 8 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleAdded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RoleAdded(String partyId, String name) implements RoleAdditionSucceeded, PublishedEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleRemoved.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RoleRemoved(String partyId, String name) implements RoleRemovalSucceeded, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleAdditionFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RoleAdditionFailed(String partyId, String role, String reason) implements PartyRelatedFailureEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleRemovalFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RoleRemovalFailed(String partyId, String role, String reason) implements PartyRelatedFailureEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PersonRolesTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class PersonRolesTest extends PartyRolesTest { 4 | 5 | PersonRolesTest() { 6 | super(Person.class); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressUseType.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | public enum AddressUseType { 4 | 5 | BILLING, 6 | MAILING, 7 | SHIPPING, 8 | RESIDENTIAL, 9 | CONTACT 10 | } 11 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressDefinitionSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface AddressDefinitionSucceeded extends AddressRelatedEvent permits GeoAddressDefined { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleAdditionSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface RoleAdditionSucceeded extends PartyRelatedEvent permits RoleAdded, RoleAdditionSkipped { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleRemovalSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface RoleRemovalSucceeded extends PartyRelatedEvent permits RoleRemovalSkipped, RoleRemoved { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/CompanyRolesTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class CompanyRolesTest extends PartyRolesTest { 4 | 5 | CompanyRolesTest() { 6 | super(Company.class); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/GeoAddressRemoved.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record GeoAddressRemoved(String addressId, String partyId) implements AddressRemovalSucceeded, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRelationshipRemoved.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PartyRelationshipRemoved(String partyRelationshipId) implements PartyRelatedEvent, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressUpdateSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface AddressUpdateSucceeded extends AddressRelatedEvent permits AddressUpdateSkipped, GeoAddressUpdated { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/IncorrectPartyTypeIdentified.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record IncorrectPartyTypeIdentified(String partyId, String expectedType) implements PartyRelatedFailureEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/events/DomainEventsPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.events; 2 | 3 | public interface DomainEventsPublisher { 4 | 5 | void publish(DomainEvent domainEvent); 6 | } 7 | -------------------------------------------------------------------------------- /configurator/src/main/java/softwarearchetypes/carconfig/Rule.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.carconfig; 2 | 3 | import softwarearchetypes.sat.Clause; 4 | 5 | import java.util.List; 6 | 7 | public interface Rule { 8 | 9 | List toClause(); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/common/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public final class StringUtils { 4 | 5 | public static boolean isNotBlank(String value) { 6 | return value != null && !value.isBlank(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressDefinitionFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface AddressDefinitionFailed extends AddressRelatedEvent permits AddressAdditionFailed, AddressUpdateFailed { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressRemovalSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface AddressRemovalSucceeded extends AddressRelatedEvent permits AddressRemovalSkipped, GeoAddressRemoved { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/OrganizationNameUpdated.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record OrganizationNameUpdated(String partyId, String value) implements OrganizationNameUpdateSucceeded, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public final class StringUtils { 4 | 5 | public static boolean isNotBlank(String value) { 6 | return value != null && !value.isBlank(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/events/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common.events; 2 | 3 | public interface EventHandler { 4 | 5 | boolean supports(PublishedEvent event); 6 | 7 | void handle(PublishedEvent event); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /general-assignment/src/main/java/softwarearchetypes/multidimensionalknapsack/WeightDimension.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.multidimensionalknapsack; 2 | 3 | public interface WeightDimension { 4 | boolean isSatisfiedBy(T capacityDimension); 5 | } 6 | -------------------------------------------------------------------------------- /party/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/RegisteredIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | //can be enhanced with validity period 4 | public interface RegisteredIdentifier { 5 | 6 | String type(); 7 | 8 | String asString(); 9 | } 10 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PersonalDataUpdated.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PersonalDataUpdated(String partyId, String firstName, String lastName) implements PersonalDataUpdateSucceeded, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/TransactionAccountEntriesView.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.List; 4 | 5 | public record TransactionAccountEntriesView(AccountMetadataView account, List entries) { 6 | 7 | } 8 | 9 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierAdditionFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RegisteredIdentifierAdditionFailed(String partyId, String identifier, String reason) implements PartyRelatedFailureEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierRemovalFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RegisteredIdentifierRemovalFailed(String partyId, String identifier, String reason) implements PartyRelatedFailureEvent { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface PartyRegistered extends PartyRelatedEvent, PublishedEvent permits CompanyRegistered, OrganizationUnitRegistered, PersonRegistered { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /configurator/src/main/java/softwarearchetypes/sat/Clause.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.sat; 2 | 3 | import java.util.List; 4 | 5 | public record Clause(List representation) { 6 | 7 | public Clause(Integer ... literals) { 8 | this(List.of(literals)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierAdded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RegisteredIdentifierAdded(String partyId, String type, String value) implements RegisteredIdentifierAdditionSucceeded, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierRemoved.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RegisteredIdentifierRemoved(String partyId, String type, String value) implements RegisteredIdentifierRemovalSucceeded, PublishedEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/OrganizationUnitRolesTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class OrganizationUnitRolesTest extends PartyRolesTest { 4 | 5 | OrganizationUnitRolesTest() { 6 | super(OrganizationUnit.class); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /waitlist/src/main/java/com/softwarearchetypes/waitlist/WaitListId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist; 2 | 3 | import java.util.UUID; 4 | 5 | record WaitListId(UUID value) { 6 | 7 | static WaitListId random() { 8 | return new WaitListId(UUID.randomUUID()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/EventsPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | 4 | public interface EventsPublisher { 5 | //remember about transactions scope 6 | void publish(PublishedEvent event); 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/EventPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.List; 4 | 5 | public interface EventPublisher { 6 | 7 | void publish(PublishedEvent event); 8 | 9 | void publish(List events); 10 | } 11 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierAdditionSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface RegisteredIdentifierAdditionSucceeded extends PartyRelatedEvent permits RegisteredIdentifierAdded, RegisteredIdentifierAdditionSkipped { 4 | } 5 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PersonRegisteredIdentifiersTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class PersonRegisteredIdentifiersTest extends PartyRegisteredIdentifiersTest { 4 | 5 | PersonRegisteredIdentifiersTest() { 6 | super(Person.class); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierRemovalSucceeded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public sealed interface RegisteredIdentifierRemovalSucceeded extends PartyRelatedEvent permits RegisteredIdentifierRemovalSkipped, RegisteredIdentifierRemoved { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/CompanyRegisteredIdentifiersTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class CompanyRegisteredIdentifiersTest extends PartyRegisteredIdentifiersTest { 4 | 5 | CompanyRegisteredIdentifiersTest() { 6 | super(Company.class); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /configurator/src/main/java/softwarearchetypes/carconfig/CarConfigId.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.carconfig; 2 | 3 | import java.util.UUID; 4 | 5 | public record CarConfigId(UUID id) { 6 | 7 | public static CarConfigId random() { 8 | return new CarConfigId(UUID.randomUUID()); 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/CompanyRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.Set; 4 | 5 | public record CompanyRegistered(String partyId, String organizationName, Set registeredIdentifiers, Set roles) implements PartyRegistered { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/events/AccountingEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.events; 2 | 3 | import com.softwarearchetypes.common.events.PublishedEvent; 4 | 5 | sealed public interface AccountingEvent extends PublishedEvent permits CreditEntryRegistered, DebitEntryRegistered { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/events/PublishedEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | public interface PublishedEvent { 7 | 8 | UUID id(); 9 | 10 | String type(); 11 | 12 | Instant occurredAt(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/ZipCode.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | public record ZipCode(String value) { 4 | 5 | public static ZipCode of(String value) { 6 | return new ZipCode(value); 7 | } 8 | 9 | public String asString() { 10 | return value; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /configurator/src/main/java/softwarearchetypes/carconfig/CarConfigProcessId.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.carconfig; 2 | 3 | import java.util.UUID; 4 | 5 | public record CarConfigProcessId(UUID id) { 6 | 7 | public static CarConfigProcessId random() { 8 | return new CarConfigProcessId(UUID.randomUUID()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /general-assignment/src/main/java/softwarearchetypes/multidimensionalknapsack/Item.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.multidimensionalknapsack; 2 | 3 | public record Item(String name, double value, TotalWeight totalWeight) { 4 | 5 | boolean isWeightZero() { 6 | return totalWeight().components().isEmpty(); 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/OrganizationUnitRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.Set; 4 | 5 | public record OrganizationUnitRegistered(String partyId, String organizationName, Set registeredIdentifiers, Set roles) implements PartyRegistered { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/OrganizationUnitRegisteredIdentifiersTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class OrganizationUnitRegisteredIdentifiersTest extends PartyRegisteredIdentifiersTest { 4 | 5 | OrganizationUnitRegisteredIdentifiersTest() { 6 | super(OrganizationUnit.class); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/OrganizationName.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | public record OrganizationName(String value) { 4 | 5 | static OrganizationName of(String value) { 6 | return new OrganizationName(value); 7 | } 8 | 9 | String asString() { 10 | return value; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PersonRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.Set; 4 | 5 | public record PersonRegistered(String partyId, String firstName, String lastName, Set registeredIdentifiers, 6 | Set roles) implements PartyRegistered { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /product/src/test/java/com/softwarearchetypes/product/ProductApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ProductApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/Unlock.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | public record Unlock(String assetId) implements Command { 4 | 5 | static final String TYPE = "UNLOCK"; 6 | 7 | @Override 8 | public String getType() { 9 | return TYPE; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/Address.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Set; 4 | 5 | public sealed interface Address extends AddressLifecycle permits GeoAddress { 6 | 7 | AddressId id(); 8 | 9 | PartyId partyId(); 10 | 11 | Set useTypes(); 12 | 13 | AddressDetails addressDetails(); 14 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRegistrationFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PartyRegistrationFailed(Throwable reason) implements PartyRelatedFailureEvent { 4 | 5 | public static PartyRegistrationFailed dueTo(Throwable reason) { 6 | return new PartyRegistrationFailed(reason); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/events/EventPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common.events; 2 | 3 | import java.util.List; 4 | 5 | public interface EventPublisher { 6 | 7 | void publish(PublishedEvent event); 8 | 9 | void publish(List events); 10 | 11 | void register(EventHandler eventHandler); 12 | } 13 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/DomainEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | //TODO: apply IDs with id generator and clock generator 7 | public interface DomainEvent { 8 | 9 | UUID id(); 10 | 11 | Instant occurredAt(); 12 | 13 | String type(); 14 | } 15 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/PostingCalculator.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.List; 4 | 5 | import com.softwarearchetypes.accounting.Transaction; 6 | 7 | public interface PostingCalculator { 8 | 9 | List calculate(TargetAccounts accounts, PostingContext context); 10 | } -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/Activate.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | public record Activate(String assetId) implements Command { 4 | 5 | static final String TYPE = "ACTIVATE"; 6 | 7 | @Override 8 | public String getType() { 9 | return TYPE; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/Register.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | public record Register(String assetId) implements Command { 4 | 5 | static final String TYPE = "REGISTER"; 6 | 7 | @Override 8 | public String getType() { 9 | return TYPE; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/Withdraw.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | public record Withdraw(String assetId) implements Command { 4 | 5 | static final String TYPE = "WITHDRAW"; 6 | 7 | @Override 8 | public String getType() { 9 | return TYPE; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/domain/AssetId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.domain; 2 | 3 | public record AssetId(String value) { 4 | 5 | public static AssetId of(String value) { 6 | return new AssetId(value); 7 | } 8 | 9 | public String asString() { 10 | return value; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/domain/OwnerId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.domain; 2 | 3 | public record OwnerId(String value) { 4 | 5 | public static OwnerId of(String value) { 6 | return new OwnerId(value); 7 | } 8 | 9 | public String asString() { 10 | return value; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/RandomUtils.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability 2 | 3 | 4 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic 5 | 6 | class RandomUtils { 7 | 8 | static String random(String placeholder) { 9 | "$placeholder-${randomAlphabetic(10)}" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pricing/src/main/java/com/softwarearchetypes/pricing/CalculatorView.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.pricing; 2 | 3 | public record CalculatorView(CalculatorId calculatorId, String name, CalculatorType type, String description) { 4 | 5 | static CalculatorView from(Calculator calc) { 6 | return new CalculatorView(calc.getId(), calc.name(), calc.getType(), calc.describe()); 7 | } 8 | } -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/Lock.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | public record Lock(String assetId, Integer durationInMinutes) implements Command { 4 | 5 | static final String TYPE = "LOCK"; 6 | 7 | @Override 8 | public String getType() { 9 | return TYPE; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/domain/OwnerIdFixture.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.domain 2 | 3 | 4 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric 5 | 6 | class OwnerIdFixture { 7 | 8 | static OwnerId someOwnerId() { 9 | OwnerId.of(randomAlphanumeric(10)) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRelationshipAdded.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PartyRelationshipAdded(String partyRelationshipId, String fromPartyId, String fromPartyRole, String toPartyId, String toPartyRole, 4 | String relationshipName) implements PartyRelatedEvent, PublishedEvent { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/OrganizationNameFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import com.softwarearchetypes.common.RandomFixture; 4 | 5 | class OrganizationNameFixture { 6 | 7 | static OrganizationName someOrganizationName() { 8 | return OrganizationName.of(RandomFixture.randomStringWithPrefixOf("organizationName")); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/LockIndefinitely.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | public record LockIndefinitely(String assetId) implements Command { 4 | 5 | static final String TYPE = "LOCK_INDEFINITELY"; 6 | 7 | @Override 8 | public String getType() { 9 | return TYPE; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/EntryId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.UUID; 4 | 5 | public record EntryId(UUID value) { 6 | 7 | public static EntryId generate() { 8 | return new EntryId(UUID.randomUUID()); 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return value.toString(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/GroupId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.UUID; 4 | 5 | public record GroupId(UUID uuid) { 6 | 7 | public static GroupId generate() { 8 | return new GroupId(UUID.randomUUID()); 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return uuid.toString(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/resources/db/changelog/db.changelog-202201081200-grant-schema-privileges.yaml: -------------------------------------------------------------------------------- 1 | databaseChangeLog: 2 | - changeSet: 3 | id: 2022-01-08 12:00 4 | author: bslota 5 | dbms: postgresql 6 | changes: 7 | - sql: 8 | comment: grant usage privilege to schema for application user 9 | sql: GRANT USAGE ON SCHEMA availability TO availability_user -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/Version.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public record Version(long value) { 4 | 5 | private static final long INITIAL_VALUE = 0L; 6 | 7 | public static Version initial() { 8 | return new Version(INITIAL_VALUE); 9 | } 10 | 11 | public static Version of(long value) { 12 | return new Version(value); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/common/Version.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public record Version(long value) { 4 | 5 | private static final long INITIAL_VALUE = 0L; 6 | 7 | public static Version initial() { 8 | return new Version(INITIAL_VALUE); 9 | } 10 | 11 | public static Version of(long value) { 12 | return new Version(value); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pricing/src/main/java/com/softwarearchetypes/pricing/CalculatorId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.pricing; 2 | 3 | import java.util.UUID; 4 | 5 | public record CalculatorId(UUID id) { 6 | 7 | public static CalculatorId generate() { 8 | return new CalculatorId(UUID.randomUUID()); 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return id.toString(); 14 | } 15 | } -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/AddressesTestSupport.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class AddressesTestSupport { 4 | 5 | private final AddressesFacade facade; 6 | 7 | AddressesTestSupport(AddressesFacade facade) { 8 | this.facade = facade; 9 | } 10 | 11 | void thereIsAddressOf(Address address) { 12 | facade.addOrUpdate(address.partyId(), address); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyApplication.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class PartyApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(PartyApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/resources/db/changelog/db.changelog-202201081202-grant-asset-availability-privileges.yaml: -------------------------------------------------------------------------------- 1 | databaseChangeLog: 2 | - changeSet: 3 | id: 2022-01-08 12:02 4 | author: bslota 5 | dbms: postgresql 6 | changes: 7 | - sql: 8 | comment: grant table permissions for application user 9 | sql: GRANT SELECT,INSERT, UPDATE, DELETE ON availability.asset_availability TO availability_user -------------------------------------------------------------------------------- /availability/simple-availability/src/test/resources/testContainers/postgresContainer.sql: -------------------------------------------------------------------------------- 1 | DO $$ 2 | BEGIN 3 | CREATE ROLE availability_user NOSUPERUSER NOCREATEDB CREATEROLE INHERIT LOGIN PASSWORD ''; 4 | EXCEPTION WHEN OTHERS THEN 5 | RAISE NOTICE 'not creating role availability_user -- it already exists'; 6 | END 7 | $$; 8 | 9 | CREATE SCHEMA IF NOT EXISTS availability; 10 | 11 | GRANT USAGE ON SCHEMA availability TO availability_user -------------------------------------------------------------------------------- /availability/timed-availability/src/test/java/com/softwarearchetypes/MockedClockConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes; 2 | 3 | import org.springframework.boot.test.context.TestConfiguration; 4 | import org.springframework.boot.test.mock.mockito.MockBean; 5 | 6 | import java.time.Clock; 7 | 8 | @TestConfiguration(proxyBeanMethods = false) 9 | public class MockedClockConfiguration { 10 | 11 | @MockBean 12 | Clock clock; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressesRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.function.Predicate; 6 | 7 | interface AddressesRepository { 8 | 9 | Optional findFor(PartyId partyId); 10 | 11 | List
findMatching(PartyId partyId, Predicate
predicate); 12 | 13 | void save(Addresses addresses); 14 | } 15 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/resources/schema-availability.sql: -------------------------------------------------------------------------------- 1 | create table if not exists availabilities ( 2 | id uuid not null, 3 | resource_id uuid not null, 4 | resource_parent_id uuid, 5 | version bigserial not null, 6 | from_date timestamp not null, 7 | to_date timestamp not null, 8 | taken_by uuid, 9 | disabled boolean not null, 10 | primary key (id), 11 | unique(resource_id, from_date, to_date)); 12 | 13 | -------------------------------------------------------------------------------- /configurator/src/test/resources/12Variables_36Clauses_SAT2.txt: -------------------------------------------------------------------------------- 1 | 1 3 -5 2 | 1 -3 -5 3 | -1 3 -5 4 | -1 -3 5 5 | 2 3 -6 6 | 2 -3 -6 7 | -2 3 -6 8 | -2 -3 6 9 | 1 4 -7 10 | 1 -4 -7 11 | -1 4 -7 12 | -1 -4 7 13 | 6 7 -8 14 | 6 -7 -8 15 | -6 7 -8 16 | -6 -7 8 17 | 6 7 -9 18 | 6 -7 9 19 | -6 7 9 20 | -6 -7 -9 21 | 2 4 -10 22 | 2 -4 -10 23 | -2 4 -10 24 | -2 -4 10 25 | 8 10 -11 26 | 8 -10 -11 27 | -8 10 -11 28 | -8 -10 11 29 | 8 10 -12 30 | 8 -10 12 31 | -8 10 12 32 | -8 -10 -12 -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ProductApplication.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ProductApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ProductApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/ClockConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes; 2 | 3 | 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.time.Clock; 8 | 9 | @Configuration 10 | public class ClockConfiguration { 11 | 12 | @Bean 13 | Clock clock() { 14 | return Clock.systemDefaultZone(); 15 | } 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /waitlist/src/main/java/com/softwarearchetypes/waitlist/WaitListApplication.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WaitListApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WaitListApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: availability 4 | jpa: 5 | hibernate: 6 | ddl-auto: none 7 | datasource: 8 | hikari: 9 | connection-init-sql: SET SESSION ROLE availability_user; 10 | schema: availability 11 | liquibase: 12 | enabled: true 13 | liquibase-schema: public 14 | kafka: 15 | consumer: 16 | properties: 17 | allow.auto.create.topics: false -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRoleDefiningPolicy.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | @FunctionalInterface 4 | interface PartyRoleDefiningPolicy { 5 | 6 | boolean canDefineFor(Party party, Role role); 7 | 8 | } 9 | 10 | final class AlwaysAllowPartyRoleDefiningPolicy implements PartyRoleDefiningPolicy { 11 | 12 | @Override 13 | public boolean canDefineFor(Party party, Role role) { 14 | return true; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/TransactionView.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.time.Instant; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public record TransactionView( 8 | TransactionId id, 9 | TransactionId refId, 10 | TransactionType type, 11 | Instant occurredAt, 12 | Instant appliesAt, 13 | List entries) { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/domain/AssetIdFixture.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.domain 2 | 3 | 4 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric 5 | 6 | class AssetIdFixture { 7 | 8 | static AssetId someAssetId() { 9 | AssetId.of(someAssetIdValue()) 10 | } 11 | 12 | static String someAssetIdValue() { 13 | randomAlphanumeric(10) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/domain/DurationFixture.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.domain 2 | 3 | 4 | import java.time.Duration 5 | 6 | import static java.time.temporal.ChronoUnit.MINUTES 7 | import static org.apache.commons.lang3.RandomUtils.nextLong 8 | 9 | class DurationFixture { 10 | 11 | static Duration someValidDuration() { 12 | Duration.of(nextLong(1, 15), MINUTES) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/PublishedEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import java.time.Instant; 4 | 5 | //metadata: 6 | //correlationId 7 | //potential aggregate's id 8 | //causationId - id of a message that caused this message 9 | //messageId - unique id of the 10 | //user - if there is any (might be a system event) 11 | public interface PublishedEvent { 12 | 13 | Instant occurredAt(); 14 | } 15 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/domain/AssetAvailabilityRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.domain; 2 | 3 | import java.util.Optional; 4 | import java.util.stream.Stream; 5 | 6 | public interface AssetAvailabilityRepository { 7 | 8 | void save(AssetAvailability assetAvailability); 9 | 10 | Optional findBy(AssetId assetId); 11 | 12 | Stream findOverdue(); 13 | } 14 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/AvailabilityApplication.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AvailabilityApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(AvailabilityApplication.class, args); 11 | 12 | } 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /configurator/src/test/resources/12Variables_36Clauses_SAT.txt: -------------------------------------------------------------------------------- 1 | 1 3 -5 2 | 1 -3 -5 3 | -1 3 -5 4 | -1 -3 5 5 | 2 3 -6 6 | 2 -3 -6 7 | -2 3 -6 8 | -2 -3 6 9 | 1 4 -7 10 | 1 -4 -7 11 | -1 4 -7 12 | -1 -4 7 13 | 6 7 -8 14 | 6 -7 -8 15 | -6 7 -8 16 | -6 -7 8 17 | 6 7 -9 18 | 6 -7 9 19 | -6 7 9 20 | -6 -7 -9 21 | 2 4 -10 22 | 2 -4 -10 23 | -2 4 -10 24 | -2 -4 10 25 | 8 10 -11 26 | 8 -10 -11 27 | -8 10 -11 28 | -8 -10 11 29 | 8 10 -12 30 | 8 -10 12 31 | -8 10 12 32 | -8 -10 -12 33 | -5 34 | 9 35 | 12 36 | -11 -------------------------------------------------------------------------------- /configurator/src/test/resources/12Variables_36Clauses_UNSAT.txt: -------------------------------------------------------------------------------- 1 | 1 3 -5 2 | 1 -3 -5 3 | -1 3 -5 4 | -1 -3 5 5 | 2 3 -6 6 | 2 -3 -6 7 | -2 3 -6 8 | -2 -3 6 9 | 1 4 -7 10 | 1 -4 -7 11 | -1 4 -7 12 | -1 -4 7 13 | 6 7 -8 14 | 6 -7 -8 15 | -6 7 -8 16 | -6 -7 8 17 | 6 7 -9 18 | 6 -7 9 19 | -6 7 9 20 | -6 -7 -9 21 | 2 4 -10 22 | 2 -4 -10 23 | -2 4 -10 24 | -2 -4 10 25 | 8 10 -11 26 | 8 -10 -11 27 | -8 10 -11 28 | -8 -10 11 29 | 8 10 -12 30 | 8 -10 12 31 | -8 10 12 32 | -8 -10 -12 33 | 5 34 | -9 35 | 12 36 | -11 -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/AvailabilityApplication.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AvailabilityApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(AvailabilityApplication.class, args); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/resources/db/changelog/db.changelog-master.yaml: -------------------------------------------------------------------------------- 1 | databaseChangeLog: 2 | - include: 3 | file: db.changelog-202201081200-grant-schema-privileges.yaml 4 | relativeToChangelogFile: true 5 | - include: 6 | file: db.changelog-202201081201-create-asset-availability-table.yaml 7 | relativeToChangelogFile: true 8 | - include: 9 | file: db.changelog-202201081202-grant-asset-availability-privileges.yaml 10 | relativeToChangelogFile: true -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressUpdateFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record AddressUpdateFailed(String reason) implements AddressDefinitionFailed { 4 | 5 | private static final String NOT_MATCHING_ADDRESS_TYPE_REASON = "NOT_MATCHING_ADDRESS_TYPE"; 6 | 7 | public static AddressUpdateFailed dueToNotMatchingAddressType() { 8 | return new AddressUpdateFailed(NOT_MATCHING_ADDRESS_TYPE_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/RelationshipNameFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; 4 | 5 | final class RelationshipNameFixture { 6 | 7 | static String someRelationshipNameValue() { 8 | return randomAlphabetic(10); 9 | } 10 | 11 | static RelationshipName someRelationshipName() { 12 | return RelationshipName.of(someRelationshipNameValue()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRoleDefinitionFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PartyRoleDefinitionFailed(String reason) implements PartyRelatedFailureEvent { 4 | 5 | private static final String POLICIES_NOT_MET_REASON = "Policies for assigning party role not met"; 6 | 7 | public static PartyRoleDefinitionFailed dueToPoliciesNotMet() { 8 | return new PartyRoleDefinitionFailed(POLICIES_NOT_MET_REASON); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/ReverseTransactionCommand.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | /** 7 | * Command for reversing an existing transaction. 8 | * Creates a reversal transaction that inverts all entries of the referenced transaction. 9 | */ 10 | public record ReverseTransactionCommand( 11 | UUID refTransactionId, 12 | Instant occurredAt, 13 | Instant appliesAt 14 | ) {} 15 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/TestPartyApplication.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.test.context.TestConfiguration; 5 | 6 | @TestConfiguration(proxyBeanMethods = false) 7 | public class TestPartyApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.from(PartyApplication::main).with(TestPartyApplication.class).run(args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/Preconditions.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public final class Preconditions { 4 | 5 | public static void checkArgument(boolean expression, String errorMessage) { 6 | if (!expression) { 7 | throw new IllegalArgumentException(errorMessage); 8 | } 9 | } 10 | 11 | public static void checkNotNull(Object value, String errorMessage) { 12 | checkArgument(value != null, errorMessage); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/common/Preconditions.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | public final class Preconditions { 4 | 5 | public static void checkArgument(boolean expression, String errorMessage) { 6 | if (!expression) { 7 | throw new IllegalArgumentException(errorMessage); 8 | } 9 | } 10 | 11 | public static void checkNotNull(Object value, String errorMessage) { 12 | checkArgument(value != null, errorMessage); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleAdditionSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RoleAdditionSkipped(String partyId, String name, String reason) implements RoleAdditionSucceeded { 4 | 5 | private static final String DUPLICATION_REASON = "DUPLICATION"; 6 | 7 | public static RoleAdditionSkipped dueToDuplicationFor(String partyId, String name) { 8 | return new RoleAdditionSkipped(partyId, name, DUPLICATION_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RoleRemovalSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RoleRemovalSkipped(String partyId, String name, String reason) implements RoleRemovalSucceeded { 4 | 5 | private static final String MISSING_ROLE_REASON = "MISSING_ROLE"; 6 | 7 | public static RoleRemovalSkipped dueToMissingRoleFor(String partyId, String name) { 8 | return new RoleRemovalSkipped(partyId, name, MISSING_ROLE_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /waitlist/src/main/java/com/softwarearchetypes/waitlist/WaitListRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist; 2 | 3 | import java.util.Optional; 4 | 5 | interface WaitListRepository { 6 | 7 | Optional findBy(WaitListId waitListId); 8 | 9 | void save(WaitList waitList); 10 | 11 | default WaitList findIfExistsBy(WaitListId waitListId) { 12 | return findBy(waitListId).orElseThrow(() -> new IllegalStateException("Wait list of given ID does not exist")); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/PostingRuleRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | interface PostingRuleRepository { 7 | 8 | List findAll(); 9 | 10 | Optional find(PostingRuleId id); 11 | 12 | void save(PostingRule rule); 13 | 14 | void delete(PostingRuleId id); 15 | 16 | List findEligibleRules(PostingContext context); 17 | } -------------------------------------------------------------------------------- /availability/timed-availability/src/test/java/com/softwarearchetypes/MockedEventPublisherConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes; 2 | 3 | import com.softwarearchetypes.availability.EventsPublisher; 4 | import org.springframework.boot.test.context.TestConfiguration; 5 | import org.springframework.boot.test.mock.mockito.MockBean; 6 | 7 | @TestConfiguration(proxyBeanMethods = false) 8 | public class MockedEventPublisherConfiguration { 9 | 10 | @MockBean 11 | EventsPublisher eventsPublisher; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/AccountId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.UUID; 4 | 5 | public record AccountId(UUID uuid) { 6 | 7 | public static AccountId generate() { 8 | return new AccountId(UUID.randomUUID()); 9 | } 10 | 11 | public static AccountId of(UUID uuid) { 12 | return new AccountId(uuid); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return uuid.toString(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressDefiningPolicy.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | @FunctionalInterface 4 | public interface AddressDefiningPolicy { 5 | 6 | boolean isAddressDefinitionAllowedFor(Addresses addresses, Address address); 7 | } 8 | 9 | final class AlwaysAllowAddressDefiningPolicy implements AddressDefiningPolicy { 10 | 11 | @Override 12 | public boolean isAddressDefinitionAllowedFor(Addresses addresses, Address address) { 13 | return true; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/PostingRule.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.List; 4 | 5 | import com.softwarearchetypes.accounting.Transaction; 6 | 7 | public interface PostingRule { 8 | 9 | PostingRuleId id(); 10 | 11 | String name(); 12 | 13 | boolean isEligible(PostingContext context); 14 | 15 | List execute(PostingContext context); 16 | 17 | default int priority() { 18 | return 100; 19 | } 20 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressAdditionFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record AddressAdditionFailed(String addressId, String partyId, String reason) implements AddressDefinitionFailed { 4 | 5 | private static final String POLICY_NOT_MET_REASON = "POLICY_NOT_MET"; 6 | 7 | public static AddressAdditionFailed dueToPolicyNotMetFor(String addressId, String partyId) { 8 | return new AddressAdditionFailed(addressId, partyId, POLICY_NOT_MET_REASON); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/SerialNumber.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | interface SerialNumber { 4 | 5 | String type(); 6 | 7 | String value(); 8 | 9 | static SerialNumber of(String value) { 10 | return TextualSerialNumber.of(value); 11 | } 12 | 13 | static SerialNumber vin(String value) { 14 | return VinSerialNumber.of(value); 15 | } 16 | 17 | static SerialNumber imei(String value) { 18 | return ImeiSerialNumber.of(value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/TransactionId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.UUID; 4 | 5 | public record TransactionId(UUID value) { 6 | 7 | public static TransactionId generate() { 8 | return new TransactionId(UUID.randomUUID()); 9 | } 10 | 11 | public static TransactionId of(UUID uuid) { 12 | return new TransactionId(uuid); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return value.toString(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PartyRelationshipTestSupport.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | class PartyRelationshipTestSupport { 4 | 5 | private final PartyRelationshipsFacade facade; 6 | 7 | PartyRelationshipTestSupport(PartyRelationshipsFacade facade) { 8 | this.facade = facade; 9 | } 10 | 11 | void thereIsARelationBetween(Party from, Role fromRole, Party to, Role toRole, RelationshipName name) { 12 | facade.assign(from.id(), fromRole, to.id(), toRole, name); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRelationshipDefiningPolicy.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | interface PartyRelationshipDefiningPolicy { 4 | 5 | boolean canDefineFor(PartyRole from, PartyRole to, RelationshipName relationshipName); 6 | } 7 | 8 | final class AlwaysAllowPartyRelationshipDefiningPolicy implements PartyRelationshipDefiningPolicy { 9 | 10 | @Override 11 | public boolean canDefineFor(PartyRole from, PartyRole to, RelationshipName relationshipName) { 12 | return true; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /product/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | .mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /accounting/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | .mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/BatchId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Unique identifier for a Batch. 7 | */ 8 | record BatchId(UUID value) { 9 | 10 | static BatchId newOne() { 11 | return new BatchId(UUID.randomUUID()); 12 | } 13 | 14 | static BatchId of(String value) { 15 | return new BatchId(UUID.fromString(value)); 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return value.toString(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /quantity/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | .mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /waitlist/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /general-assignment/src/main/java/softwarearchetypes/multidimensionalknapsack/Result.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.multidimensionalknapsack; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | public record Result(Double profit, List chosenItems, Map> itemToCapacities) { 8 | @Override 9 | public String toString() { 10 | return "Result{" + 11 | "profit=" + profit + 12 | ", chosenItems=" + chosenItems + 13 | '}'; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressRemovalSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record AddressRemovalSkipped(String addressId, String partyId, String reason) implements AddressRemovalSucceeded { 4 | 5 | private static final String ADDRESS_NOT_FOUND_REASON = "ADDRESS_NOT_FOUND"; 6 | 7 | public static AddressRemovalSkipped dueToAddressNotFoundFor(String addressId, String partyId) { 8 | return new AddressRemovalSkipped(addressId, partyId, ADDRESS_NOT_FOUND_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /party/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | notes.md 3 | target/ 4 | !.mvn/wrapper/maven-wrapper.jar 5 | !**/src/main/**/target/ 6 | !**/src/test/**/target/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | 23 | ### NetBeans ### 24 | /nbproject/private/ 25 | /nbbuild/ 26 | /dist/ 27 | /nbdist/ 28 | /.nb-gradle/ 29 | build/ 30 | !**/src/main/**/build/ 31 | !**/src/test/**/build/ 32 | 33 | ### VS Code ### 34 | .vscode/ 35 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/Role.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | import static com.softwarearchetypes.common.StringUtils.isNotBlank; 5 | 6 | public record Role(String name) { 7 | 8 | public Role { 9 | checkArgument(isNotBlank(name), "Role name cannot be null"); 10 | } 11 | 12 | static Role of(String value) { 13 | return new Role(value); 14 | } 15 | 16 | String asString() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/AddressUpdateSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record AddressUpdateSkipped(String addressId, String partyId, String reason) implements AddressUpdateSucceeded { 4 | 5 | private static final String NO_CHANGES_IDENTIFIED_REASON = "NO_CHANGES_IDENTIFIED"; 6 | 7 | public static AddressUpdateSkipped dueToNoChangesIdentifiedFor(String addressId, String partyId) { 8 | return new AddressUpdateSkipped(addressId, partyId, NO_CHANGES_IDENTIFIED_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PersonTestDataBuilder.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | final class PersonTestDataBuilder extends PartyAbstractTestDataBuilder { 4 | 5 | PersonalData personalData = PersonalData.empty(); 6 | 7 | PersonTestDataBuilder with(PersonalData personalData) { 8 | this.personalData = personalData; 9 | return this; 10 | } 11 | 12 | @Override 13 | Person build() { 14 | return new Person(partyId, personalData, roles, registeredIdentifiers, version); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ProductName.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | 5 | record ProductName(String value) { 6 | 7 | ProductName { 8 | checkArgument(value != null && !value.isBlank(), "ProductName cannot be null or blank"); 9 | } 10 | 11 | static ProductName of(String value) { 12 | return new ProductName(value); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/PostingRuleId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.UUID; 4 | 5 | public record PostingRuleId(UUID uuid) { 6 | 7 | public static PostingRuleId generate() { 8 | return new PostingRuleId(UUID.randomUUID()); 9 | } 10 | 11 | public static PostingRuleId of(String uuid) { 12 | return new PostingRuleId(UUID.fromString(uuid)); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return uuid.toString(); 18 | } 19 | } -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressLifecycle.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import com.softwarearchetypes.party.events.AddressDefinitionSucceeded; 4 | import com.softwarearchetypes.party.events.AddressRemovalSucceeded; 5 | import com.softwarearchetypes.party.events.AddressUpdateSucceeded; 6 | 7 | interface AddressLifecycle { 8 | 9 | AddressUpdateSucceeded toAddressUpdateSucceededEvent(); 10 | 11 | AddressDefinitionSucceeded toAddressDefinitionSucceededEvent(); 12 | 13 | AddressRemovalSucceeded toAddressRemovalSucceededEvent(); 14 | } -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/CompanyTestDataBuilder.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | final class CompanyTestDataBuilder extends PartyAbstractTestDataBuilder { 4 | 5 | OrganizationName organizationName; 6 | 7 | CompanyTestDataBuilder with(OrganizationName organizationName) { 8 | this.organizationName = organizationName; 9 | return this; 10 | } 11 | 12 | @Override 13 | Company build() { 14 | return new Company(partyId, organizationName, roles, registeredIdentifiers, version); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/events/DebitEntryRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | import com.softwarearchetypes.quantity.money.Money; 7 | 8 | public record DebitEntryRegistered(UUID id, Instant occurredAt, Instant appliesAt, UUID entryId, UUID accountId, UUID transactionId, Money amount) implements AccountingEvent { 9 | 10 | static final String TYPE = "DebitEntryRegistered"; 11 | 12 | public String type() { 13 | return TYPE; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/events/CreditEntryRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | import com.softwarearchetypes.quantity.money.Money; 7 | 8 | public record CreditEntryRegistered(UUID id, Instant occurredAt, Instant appliesAt, UUID entryId, UUID accountId, UUID transactionId, Money amount) implements AccountingEvent { 9 | 10 | static final String TYPE = "CreditEntryRegistered"; 11 | 12 | public String type() { 13 | return TYPE; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Archetypy Oprogramowania 2 | 3 | [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) 4 | 5 | ## Licencja 6 | 7 | Ten projekt jest dostępny na licencji **CC BY-NC-SA 4.0** (Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International). 8 | 9 | ✅ Możesz używać kodu do nauki i projektów niekomercyjnych 10 | ❌ Użycie komercyjne wymaga kontaktu z autorami 11 | 12 | Więcej informacji w pliku [LICENSE](LICENSE). 13 | 14 | ## Autorzy 15 | 16 | - Bartłomiej Słota 17 | - Jakub Pilimon 18 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/OrganizationNameUpdateSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record OrganizationNameUpdateSkipped(String partyId, String value, String reason) implements OrganizationNameUpdateSucceeded { 4 | 5 | private static final String NO_CHANGE_IDENTIFIED_REASON = "NO_CHANGE_IDENTIFIED"; 6 | 7 | public static OrganizationNameUpdateSkipped dueToNoChangeIdentifiedFor(String partyId, String value) { 8 | return new OrganizationNameUpdateSkipped(partyId, value, NO_CHANGE_IDENTIFIED_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ProductDescription.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | 5 | record ProductDescription(String value) { 6 | 7 | ProductDescription { 8 | checkArgument(value != null && !value.isBlank(), "ProductDescription cannot be null or blank"); 9 | } 10 | 11 | static ProductDescription of(String value) { 12 | return new ProductDescription(value); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/ResourceTakenOver.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import java.time.Instant; 4 | import java.util.Set; 5 | import java.util.UUID; 6 | 7 | public record ResourceTakenOver(UUID eventId, ResourceId resourceId, Set previousOwners, TimeSlot slot, Instant occurredAt) implements PublishedEvent { 8 | 9 | public ResourceTakenOver(ResourceId resourceId, Set previousOwners, TimeSlot slot, Instant occuredAt) { 10 | this(UUID.randomUUID(), resourceId, previousOwners, slot, occuredAt); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.function.Predicate; 6 | 7 | public interface PartyRepository { 8 | 9 | Optional findBy(PartyId partyId); 10 | 11 | Optional findBy(PartyId partyId, Class partyType); 12 | 13 | void save(Party party); 14 | 15 | void delete(PartyId partyId); 16 | 17 | List findBy(RegisteredIdentifier registeredIdentifier); 18 | 19 | List findMatching(Predicate predicate); 20 | } 21 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/common/CollectionFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | 7 | public class CollectionFixture { 8 | 9 | public static Set copyAndAdd(Set collection, T element) { 10 | Set copy = new HashSet<>(collection); 11 | copy.add(element); 12 | return copy; 13 | } 14 | 15 | public static Set stringSetFrom(Set> set) { 16 | return set.stream().map(Enum::name).collect(Collectors.toSet()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierAdditionSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RegisteredIdentifierAdditionSkipped(String partyId, String type, String value, String reason) implements RegisteredIdentifierAdditionSucceeded { 4 | 5 | private static final String DUPLICATION_REASON = "DUPLICATION"; 6 | 7 | public static RegisteredIdentifierAdditionSkipped dueToDataDuplicationFor(String partyId, String type, String value) { 8 | return new RegisteredIdentifierAdditionSkipped(partyId, type, value, DUPLICATION_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PersonalDataUpdateSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PersonalDataUpdateSkipped(String partyId, String firstName, String lastName, String reason) implements PersonalDataUpdateSucceeded { 4 | 5 | private static final String NO_CHANGE_IDENTIFIED_REASON = "NO_CHANGE_IDENTIFIED"; 6 | 7 | public static PersonalDataUpdateSkipped dueToNoChangeIdentifiedFor(String partyId, String firstName, String lastName) { 8 | return new PersonalDataUpdateSkipped(partyId, firstName, lastName, NO_CHANGE_IDENTIFIED_REASON); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/OrganizationUnitTestDataBuilder.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | final class OrganizationUnitTestDataBuilder extends PartyAbstractTestDataBuilder { 4 | 5 | OrganizationName organizationName; 6 | 7 | OrganizationUnitTestDataBuilder with(OrganizationName organizationName) { 8 | this.organizationName = organizationName; 9 | return this; 10 | } 11 | 12 | @Override 13 | OrganizationUnit build() { 14 | return new OrganizationUnit(partyId, organizationName, roles, registeredIdentifiers, version); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/RelationshipName.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | import static com.softwarearchetypes.common.StringUtils.isNotBlank; 5 | 6 | public record RelationshipName(String value) { 7 | 8 | public RelationshipName { 9 | checkArgument(isNotBlank(value), "Relationship name cannot be null"); 10 | } 11 | 12 | static RelationshipName of(String value) { 13 | return new RelationshipName(value); 14 | } 15 | 16 | String asString() { 17 | return value; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/RegisteredIdentifierRemovalSkipped.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record RegisteredIdentifierRemovalSkipped(String partyId, String type, String value, String reason) implements RegisteredIdentifierRemovalSucceeded { 4 | 5 | private static final String MISSING_IDENTIFIER_REASON = "MISSING_IDENTIFIER"; 6 | 7 | public static RegisteredIdentifierRemovalSkipped dueToMissingIdentifierFor(String partyId, String type, String value) { 8 | return new RegisteredIdentifierRemovalSkipped(partyId, type, value, MISSING_IDENTIFIER_REASON); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/common/RandomFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common; 2 | 3 | import java.util.Collection; 4 | 5 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; 6 | import static org.apache.commons.lang3.RandomUtils.nextInt; 7 | 8 | public class RandomFixture { 9 | 10 | public static T randomElementOf(Collection collection) { 11 | return collection.stream().toList().get(nextInt(0, collection.size())); 12 | } 13 | 14 | public static String randomStringWithPrefixOf(String prefix) { 15 | return prefix + "-" + randomAlphabetic(10); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/resources/db/changelog/db.changelog-202201081201-create-asset-availability-table.yaml: -------------------------------------------------------------------------------- 1 | databaseChangeLog: 2 | - changeSet: 3 | id: 2022-01-08 12:01 4 | author: bslota 5 | changes: 6 | - createTable: 7 | schemaName: availability 8 | tableName: asset_availability 9 | columns: 10 | - column: 11 | name: asset_id 12 | type: varchar(128) 13 | constraints: 14 | primaryKey: true 15 | - column: 16 | name: lock 17 | type: varchar(1024) -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/Owner.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import java.util.UUID; 4 | 5 | public record Owner(UUID owner) { 6 | 7 | static Owner none() { 8 | return new Owner(null); 9 | } 10 | 11 | public static Owner newOne() { 12 | return new Owner(UUID.randomUUID()); 13 | } 14 | 15 | public static Owner of(UUID id) { 16 | return new Owner(id); 17 | } 18 | 19 | public boolean byNone() { 20 | return none().equals(this); 21 | } 22 | 23 | public UUID id() { 24 | return owner; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /waitlist/src/main/java/com/softwarearchetypes/waitlist/Element.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist; 2 | 3 | import java.util.UUID; 4 | 5 | record Element(UUID value, int priority) implements Comparable { 6 | 7 | private static final int DEFAULT_PRIORITY = 1; 8 | 9 | static Element of(UUID value, int priority) { 10 | return new Element(value, priority); 11 | } 12 | 13 | static Element of(UUID value) { 14 | return new Element(value, DEFAULT_PRIORITY); 15 | } 16 | 17 | @Override 18 | public int compareTo(Element o) { 19 | return Integer.compare(this.priority, o.priority); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/BatchName.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | 5 | /** 6 | * Descriptive name for a Batch (e.g., "Batch 2024-Q1-001", "LOT-20240115-A"). 7 | */ 8 | record BatchName(String value) { 9 | 10 | BatchName { 11 | checkArgument(value != null && !value.isBlank(), "BatchName cannot be null or blank"); 12 | } 13 | 14 | static BatchName of(String value) { 15 | return new BatchName(value); 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return value; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/CreateAccount.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | public record CreateAccount(AccountId accountId, String name, String type) { 4 | 5 | public static CreateAccount generateAssetAccount(AccountId accountId) { 6 | return new CreateAccount(accountId, "", "ASSET"); 7 | } 8 | 9 | public static CreateAccount generateAssetAccount(String name) { 10 | return new CreateAccount(AccountId.generate(), name, "ASSET"); 11 | } 12 | 13 | public static CreateAccount generate(String type) { 14 | return new CreateAccount(AccountId.generate(), "", type); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.UUID; 4 | 5 | import static com.softwarearchetypes.common.Preconditions.checkNotNull; 6 | 7 | public record AddressId(UUID value) { 8 | 9 | public AddressId { 10 | checkNotNull(value, "Address ID needs to be valid UUID"); 11 | } 12 | 13 | public static AddressId of(UUID value) { 14 | return new AddressId(value); 15 | } 16 | 17 | public static AddressId random() { 18 | return of(UUID.randomUUID()); 19 | } 20 | 21 | public String asString() { 22 | return value.toString(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /general-assignment/src/main/java/softwarearchetypes/multidimensionalknapsack/TotalWeight.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.multidimensionalknapsack; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | public record TotalWeight(List components) { 9 | 10 | static TotalWeight zero() { 11 | return new TotalWeight(List.of()); 12 | } 13 | 14 | public static TotalWeight of(WeightDimension... components) { 15 | return new TotalWeight(Arrays.asList(components)); 16 | } 17 | 18 | public List components() { 19 | return new ArrayList<>(components); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PersonalDataFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; 4 | 5 | class PersonalDataFixture { 6 | 7 | static String someFirstName() { 8 | return randomAlphabetic(10); 9 | } 10 | 11 | static String someLastName() { 12 | return randomAlphabetic(10); 13 | } 14 | 15 | static PersonalData somePersonalData() { 16 | return PersonalData.from(someFirstName(), someLastName()); 17 | } 18 | 19 | static PersonalData nameOf(String firstName) { 20 | return PersonalData.from(firstName, null); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/PartyRelationshipDefinitionFailed.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | public record PartyRelationshipDefinitionFailed(String reason) implements PartyRelatedFailureEvent { 4 | 5 | private static final String POLICIES_NOT_MET_REASON = "Policies for defining party relationship not met"; 6 | 7 | public static PartyRelationshipDefinitionFailed dueToPoliciesNotMet() { 8 | return new PartyRelationshipDefinitionFailed(POLICIES_NOT_MET_REASON); 9 | } 10 | 11 | public static PartyRelationshipDefinitionFailed dueTo(String reason) { 12 | return new PartyRelationshipDefinitionFailed(reason); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PersonalData.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Optional; 4 | 5 | public record PersonalData(String firstName, String lastName) { 6 | 7 | private static final String EMPTY = ""; 8 | 9 | public PersonalData { 10 | firstName = Optional.ofNullable(firstName).orElse(EMPTY); 11 | lastName = Optional.ofNullable(lastName).orElse(EMPTY); 12 | } 13 | 14 | public static PersonalData from(String firstName, String lastName) { 15 | return new PersonalData(firstName, lastName); 16 | } 17 | 18 | static PersonalData empty() { 19 | return new PersonalData(EMPTY, EMPTY); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.UUID; 4 | 5 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 6 | import static java.util.Objects.requireNonNull; 7 | 8 | public record PartyId(UUID value) { 9 | public PartyId { 10 | checkArgument(value != null, "Party Id value cannot be null"); 11 | } 12 | 13 | public String asString() { 14 | return value.toString(); 15 | } 16 | 17 | public static PartyId of(UUID value) { 18 | return new PartyId(value); 19 | } 20 | 21 | public static PartyId random() { 22 | return of(UUID.randomUUID()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/ResourceAvailabilityId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import java.util.UUID; 4 | 5 | public record ResourceAvailabilityId(UUID id) { 6 | 7 | static ResourceAvailabilityId none() { 8 | return new ResourceAvailabilityId(null); 9 | } 10 | 11 | public static ResourceAvailabilityId newOne() { 12 | return new ResourceAvailabilityId(UUID.randomUUID()); 13 | } 14 | 15 | public static ResourceAvailabilityId of(String id) { 16 | if (id == null) { 17 | return none(); 18 | } 19 | return new ResourceAvailabilityId(UUID.fromString(id)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/GeoAddressUpdated.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.Set; 4 | 5 | public record GeoAddressUpdated(String addressId, 6 | String partyId, 7 | String name, 8 | String street, 9 | String building, 10 | String flat, 11 | String city, 12 | String zip, 13 | String locale, 14 | Set useTypes) implements AddressUpdateSucceeded, PublishedEvent { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/AddressesQueries.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.function.Predicate; 6 | 7 | public class AddressesQueries { 8 | 9 | private final AddressesRepository repository; 10 | 11 | AddressesQueries(AddressesRepository repository) { 12 | this.repository = repository; 13 | } 14 | 15 | public Optional findFor(PartyId partyId) { 16 | return repository.findFor(partyId); 17 | } 18 | 19 | public List
findMatching(PartyId partyId, Predicate
predicate) { 20 | return repository.findMatching(partyId, predicate); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/GeoAddressDefined.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.Set; 4 | 5 | public record GeoAddressDefined(String addressId, 6 | String partyId, 7 | String name, 8 | String street, 9 | String building, 10 | String flat, 11 | String city, 12 | String zip, 13 | String locale, 14 | Set useTypes) implements AddressDefinitionSucceeded, PublishedEvent { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRelationshipId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.UUID; 4 | 5 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 6 | 7 | public record PartyRelationshipId(UUID value) { 8 | 9 | public PartyRelationshipId { 10 | checkArgument(value != null, "Party relationship id value cannot be null"); 11 | } 12 | 13 | public String asString() { 14 | return value.toString(); 15 | } 16 | 17 | public static PartyRelationshipId of(UUID value) { 18 | return new PartyRelationshipId(value); 19 | } 20 | 21 | public static PartyRelationshipId random() { 22 | return of(UUID.randomUUID()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /waitlist/src/main/java/com/softwarearchetypes/waitlist/InMemoryWaitListRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist; 2 | 3 | import java.util.Optional; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | class InMemoryWaitListRepository implements WaitListRepository { 10 | 11 | private final ConcurrentHashMap map = new ConcurrentHashMap<>(); 12 | 13 | @Override 14 | public Optional findBy(WaitListId waitListId) { 15 | return Optional.ofNullable(map.get(waitListId)); 16 | } 17 | 18 | @Override 19 | public void save(WaitList waitList) { 20 | map.put(waitList.id(), waitList); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/AvailabilityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | 8 | import java.time.Clock; 9 | 10 | @Configuration 11 | public class AvailabilityConfiguration { 12 | 13 | @Bean 14 | AvailabilityFacade availabilityFacade(JdbcTemplate jdbcTemplate, EventsPublisher eventsPublisher, Clock clock) { 15 | return new AvailabilityFacade(new ResourceAvailabilityRepository(jdbcTemplate), new ResourceAvailabilityReadModel(jdbcTemplate), eventsPublisher, clock); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/BusinessContext.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | public interface BusinessContext { 7 | 8 | Map data(); 9 | 10 | default Optional get(String key, Class type) { 11 | Object value = data().get(key); 12 | if (type.isInstance(value)) { 13 | return Optional.of(type.cast(value)); 14 | } 15 | return Optional.empty(); 16 | } 17 | 18 | static BusinessContext empty() { 19 | return Map::of; 20 | } 21 | 22 | static BusinessContext of(Map data) { 23 | return () -> Map.copyOf(data); 24 | } 25 | } -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/application/InMemoryDomainEventPublisher.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.application 2 | 3 | import com.softwarearchetypes.availability.events.DomainEvent 4 | import com.softwarearchetypes.availability.events.DomainEventsPublisher 5 | 6 | class InMemoryDomainEventPublisher implements DomainEventsPublisher { 7 | 8 | List events = [] 9 | 10 | @Override 11 | void publish(DomainEvent domainEvent) { 12 | events << domainEvent 13 | } 14 | 15 | void cleanup() { 16 | events.clear() 17 | } 18 | 19 | boolean thereWasAnEventFulfilling(Closure condition) { 20 | events.find(condition).any() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRelationship.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import com.softwarearchetypes.party.events.PartyRelationshipAdded; 4 | 5 | public record PartyRelationship(PartyRelationshipId id, PartyRole from, PartyRole to, RelationshipName name) { 6 | 7 | static PartyRelationship from(PartyRelationshipId id, PartyRole from, PartyRole to, RelationshipName name) { 8 | return new PartyRelationship(id, from, to, name); 9 | } 10 | 11 | PartyRelationshipAdded toPartyRelationshipAddedEvent() { 12 | return new PartyRelationshipAdded(id.asString(), from.partyId().asString(), 13 | from.role().asString(), to.partyId().asString(), to.role().asString(), name.asString()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRelationshipRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.function.Predicate; 6 | 7 | public interface PartyRelationshipRepository { 8 | 9 | List findAllRelationsFrom(PartyId partyId); 10 | 11 | List findAllRelationsFrom(PartyId partyId, RelationshipName name); 12 | 13 | Optional findBy(PartyRelationshipId relationshipId); 14 | 15 | void save(PartyRelationship partyRelationship); 16 | 17 | Optional delete(PartyRelationshipId relationshipId); 18 | 19 | List findMatching(Predicate predicate); 20 | } 21 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRole.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | import static com.softwarearchetypes.common.StringUtils.isNotBlank; 5 | 6 | //TODO: combine with Party? 7 | public record PartyRole(PartyId partyId, Role role) { 8 | 9 | public PartyRole { 10 | checkArgument(partyId != null, "PartyId cannot be null"); 11 | checkArgument(role != null, "Role cannot be null"); 12 | } 13 | 14 | static PartyRole of(PartyId partyId, String value) { 15 | return of(partyId, Role.of(value)); 16 | } 17 | 18 | static PartyRole of(PartyId partyId, Role role) { 19 | return new PartyRole(partyId, role); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PartyRelationshipFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.function.Supplier; 4 | 5 | class PartyRelationshipFixture { 6 | 7 | public static class FixablePartyRelationshipIdSupplier implements Supplier { 8 | 9 | private PartyRelationshipId fixedValue; 10 | 11 | public void clear() { 12 | fixedValue = null; 13 | } 14 | 15 | public void fixPartyRelationshipIdTo(PartyRelationshipId value) { 16 | fixedValue = value; 17 | } 18 | 19 | @Override 20 | public PartyRelationshipId get() { 21 | return fixedValue != null ? fixedValue : PartyRelationshipId.random(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/Blockade.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | record Blockade(Owner takenBy, boolean disabled) { 4 | 5 | static Blockade none() { 6 | return new Blockade(Owner.none(), false); 7 | } 8 | 9 | public static Blockade disabledBy(Owner owner) { 10 | return new Blockade(owner, true); 11 | } 12 | 13 | public static Blockade ownedBy(Owner owner) { 14 | return new Blockade(owner, false); 15 | } 16 | 17 | boolean canBeTakenBy(Owner requester) { 18 | return takenBy.byNone() || takenBy.equals(requester); 19 | } 20 | 21 | boolean isDisabledBy(Owner owner) { 22 | return disabled && owner.equals(this.takenBy); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /party/diagrams/party-relationship-model.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 100 3 | skinparam linetype ortho 4 | 5 | object Party 6 | object Person 7 | object Organization 8 | object PartyRelationship { 9 | name: String 10 | } 11 | 12 | object Company 13 | 14 | object OrganizationUnit 15 | 16 | object PartyRole { 17 | name: String 18 | } 19 | 20 | object PartyRelationshipIdentifier { 21 | value: UUID 22 | } 23 | 24 | PartyRelationship "1" *-left- "1" PartyRelationshipIdentifier 25 | 26 | Person --up-|> Party 27 | Organization --up-|> Party 28 | Company -up-|> Organization 29 | OrganizationUnit -up-|> Organization 30 | 31 | PartyRelationship "0..*" -up- "from 1" PartyRole 32 | PartyRelationship "0..*" -up- "to 1" PartyRole 33 | 34 | Party "1" -- "0..*" PartyRole 35 | 36 | @enduml -------------------------------------------------------------------------------- /waitlist/src/test/groovy/com/softwarearchetypes/waitlist/WaitListFixture.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.waitlist 2 | 3 | class WaitListFixture { 4 | 5 | static int someValidCapacity() { 6 | new Random().nextInt(10) + 1 7 | } 8 | 9 | static List polledElementsFrom(WaitList waitList) { 10 | List polledElements = [] 11 | for (int i in 1..waitList.size()) { 12 | polledElements.add(waitList.poll()) 13 | } 14 | polledElements 15 | } 16 | 17 | static List polledValuesFrom(WaitList waitList) { 18 | List polledValues = [] 19 | for (int i in 1..waitList.size()) { 20 | polledValues.add(waitList.poll().value()) 21 | } 22 | polledValues 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /party/diagrams/party-basic-model.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 100 3 | skinparam linetype ortho 4 | 5 | object Party 6 | object Person 7 | object Organization 8 | 9 | object Company 10 | object JointStock 11 | object LimitedLiability 12 | object LimitedPartnership 13 | 14 | object OrganizationUnit 15 | object Division 16 | object Department 17 | object Team 18 | 19 | object PartyRole 20 | 21 | Person -up-|> Party 22 | Organization -up-|> Party 23 | Company -up-|> Organization 24 | JointStock --up-|> Company 25 | LimitedLiability --up-|> Company 26 | LimitedPartnership --up-|> Company 27 | OrganizationUnit -up-|> Organization 28 | Division --up-|> OrganizationUnit 29 | Department --up-|> OrganizationUnit 30 | Team --up-|> OrganizationUnit 31 | 32 | Party "1" -- "0..*" PartyRole 33 | 34 | @enduml -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/segment/Segments.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.segment; 2 | 3 | import com.softwarearchetypes.availability.TimeSlot; 4 | 5 | import java.util.List; 6 | 7 | public class Segments { 8 | 9 | public static final int DEFAULT_SEGMENT_DURATION_IN_MINUTES = 60; 10 | 11 | public static List split(TimeSlot timeSlot, SegmentInMinutes unit) { 12 | TimeSlot normalizedSlot = normalizeToSegmentBoundaries(timeSlot, unit); 13 | return new SlotToSegments().apply(normalizedSlot, unit); 14 | } 15 | 16 | public static TimeSlot normalizeToSegmentBoundaries(TimeSlot timeSlot, SegmentInMinutes unit) { 17 | return new SlotToNormalizedSlot().apply(timeSlot, unit); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/TargetAccounts.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | import com.softwarearchetypes.accounting.AccountView; 7 | 8 | public record TargetAccounts(Map accounts) { 9 | 10 | public Optional get(String tag) { 11 | return Optional.ofNullable(accounts.get(tag)); 12 | } 13 | 14 | public AccountView getRequired(String tag) { 15 | return get(tag).orElseThrow(() -> new IllegalArgumentException("Required account with tag '" + tag + "' not found")); 16 | } 17 | 18 | public static TargetAccounts of(Map accounts) { 19 | return new TargetAccounts(Map.copyOf(accounts)); 20 | } 21 | } -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/RoleFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Set; 4 | import java.util.stream.IntStream; 5 | 6 | import static java.util.stream.Collectors.toSet; 7 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; 8 | 9 | final class RoleFixture { 10 | 11 | static String someRoleName() { 12 | return randomAlphabetic(10); 13 | } 14 | 15 | static Role someRole() { 16 | return Role.of(someRoleName()); 17 | } 18 | 19 | static Set someRoleSetOfSize(int size) { 20 | return IntStream.range(0, size).mapToObj(it -> someRole()).collect(toSet()); 21 | } 22 | 23 | static Set stringSetFrom(Set roles) { 24 | return roles.stream().map(Role::asString).collect(toSet()); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /configurator/src/main/java/softwarearchetypes/carconfig/CarConfigurationProcessRepository.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.carconfig; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class CarConfigurationProcessRepository { 7 | private final Map processes = new HashMap<>(); 8 | 9 | public CarConfigurationProcess load(CarConfigProcessId carConfigProcessId) { 10 | CarConfigurationProcess process = processes.get(carConfigProcessId); 11 | if(process == null) throw new IllegalArgumentException("Cannot find process with given id"); 12 | return process; 13 | } 14 | 15 | public void addProcess(CarConfigProcessId carConfigProcessId, CarConfigurationProcess carConfigurationProcess) { 16 | processes.put(carConfigProcessId, carConfigurationProcess); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/events/BaseDomainEvent.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | public abstract class BaseDomainEvent implements DomainEvent { 7 | 8 | private final UUID id; 9 | private final Instant occurredAt; 10 | 11 | public BaseDomainEvent() { 12 | this.id = UUID.randomUUID(); 13 | this.occurredAt = Instant.now(); //Clock should be used here 14 | } 15 | 16 | BaseDomainEvent(UUID id, Instant occurredAt) { 17 | this.id = id; 18 | this.occurredAt = occurredAt; 19 | } 20 | 21 | @Override 22 | public UUID getId() { 23 | return id; 24 | } 25 | 26 | @Override 27 | public Instant getOccurredAt() { 28 | return occurredAt; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /party/diagrams/party-addresses-model.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 150 3 | skinparam linetype ortho 4 | 5 | object Party 6 | object PartyIdentifier { 7 | value: UUID 8 | } 9 | 10 | object Address { 11 | validFrom: Date 12 | validTo: Date 13 | } 14 | object AddressId { 15 | value: UUID 16 | } 17 | object AddressUseType { 18 | value: String 19 | } 20 | object EmailAddress { 21 | value: String 22 | } 23 | object GeographicAddress { 24 | addressLine: String[] 25 | city: String 26 | region: String 27 | zipCode: String 28 | } 29 | object WebPageAddress { 30 | url: String 31 | } 32 | 33 | Party "1" *- "1" PartyIdentifier 34 | Party "1" --- "0..*" Address 35 | Address "1" *-- "1..*" AddressUseType 36 | Address "1" *-- "1*" AddressId 37 | 38 | EmailAddress --up-|> Address 39 | GeographicAddress --up-|> Address 40 | WebPageAddress --up-|> Address 41 | @enduml -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/UuidProductIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Simple UUID-based ProductIdentifier implementation. 7 | * Use when you don't need to interoperate with external standard systems (ISBN, GTIN, etc.) 8 | */ 9 | record UuidProductIdentifier(UUID value) implements ProductIdentifier { 10 | 11 | static UuidProductIdentifier newOne() { 12 | return new UuidProductIdentifier(UUID.randomUUID()); 13 | } 14 | 15 | static UuidProductIdentifier of(String value) { 16 | return new UuidProductIdentifier(UUID.fromString(value)); 17 | } 18 | 19 | @Override 20 | public String type() { 21 | return "UUID"; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return value.toString(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/events/InMemoryEventsPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party.events; 2 | 3 | import java.util.HashSet; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public class InMemoryEventsPublisher implements EventPublisher { 8 | 9 | private Set observers = new HashSet<>(); 10 | 11 | @Override 12 | public void publish(PublishedEvent event) { 13 | observers.forEach(it -> it.handle(event)); 14 | } 15 | 16 | @Override 17 | public void publish(List events) { 18 | events.forEach(this::publish); 19 | } 20 | 21 | public void register(InMemoryEventObserver observer) { 22 | observers.add(observer); 23 | } 24 | 25 | public interface InMemoryEventObserver { 26 | 27 | void handle(PublishedEvent event); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/com/softwarearchetypes/common/events/InMemoryEventsPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.common.events; 2 | 3 | import java.util.HashSet; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public class InMemoryEventsPublisher implements EventPublisher { 8 | 9 | private final Set observers = new HashSet<>(); 10 | 11 | @Override 12 | public void publish(PublishedEvent event) { 13 | observers.forEach(it -> { 14 | if (it.supports(event)) { 15 | it.handle(event); 16 | } 17 | }); 18 | } 19 | 20 | @Override 21 | public void publish(List events) { 22 | events.forEach(this::publish); 23 | } 24 | 25 | @Override 26 | public void register(EventHandler eventHandler) { 27 | observers.add(eventHandler); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/infrastructure/events/SpringEventPublisher.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.infrastructure.events; 2 | 3 | import org.springframework.context.ApplicationEventPublisher; 4 | import org.springframework.stereotype.Component; 5 | 6 | import com.softwarearchetypes.availability.events.DomainEvent; 7 | import com.softwarearchetypes.availability.events.DomainEventsPublisher; 8 | 9 | @Component 10 | class SpringEventPublisher implements DomainEventsPublisher { 11 | 12 | private final ApplicationEventPublisher eventPublisher; 13 | 14 | SpringEventPublisher(ApplicationEventPublisher eventPublisher) { 15 | this.eventPublisher = eventPublisher; 16 | } 17 | 18 | @Override 19 | public void publish(DomainEvent domainEvent) { 20 | eventPublisher.publishEvent(domainEvent); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/PredefinedPollingConditions.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability 2 | 3 | import groovy.transform.CompileStatic 4 | import spock.util.concurrent.PollingConditions 5 | 6 | @CompileStatic 7 | class PredefinedPollingConditions { 8 | static final PollingConditions SHORT_WAIT = new PollingConditions(timeout: DEFAULT_SHORT) 9 | static final PollingConditions WAIT = new PollingConditions(timeout: DEFAULT_MEDIUM) 10 | static final PollingConditions LONG_WAIT = new PollingConditions(timeout: DEFAULT_LONG) 11 | static final PollingConditions SHORT_WAIT_WITH_INITIAL_DELAY = new PollingConditions(timeout: DEFAULT_SHORT + 1, initialDelay: 1) 12 | 13 | private static final int DEFAULT_SHORT = 3 14 | private static final int DEFAULT_MEDIUM = 10 15 | private static final int DEFAULT_LONG = 30 16 | } 17 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/TransactionRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Optional; 6 | 7 | interface TransactionRepository { 8 | 9 | Optional find(TransactionId transactionId); 10 | 11 | Transaction save(Transaction transaction); 12 | 13 | } 14 | 15 | class InMemoryTransactionRepo implements TransactionRepository { 16 | 17 | private final Map transactions = new HashMap<>(); 18 | 19 | @Override 20 | public Optional find(TransactionId transactionId) { 21 | return Optional.ofNullable(transactions.get(transactionId)); 22 | } 23 | 24 | @Override 25 | public Transaction save(Transaction transaction) { 26 | return transactions.put(transaction.id(), transaction); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/Calendars.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | public record Calendars(Map calendars) { 7 | 8 | public static Calendars of(com.softwarearchetypes.availability.Calendar... calendars) { 9 | Map collect = 10 | Arrays.stream(calendars) 11 | .collect(Collectors.toMap(com.softwarearchetypes.availability.Calendar::resourceId, calendar -> calendar)); 12 | return new Calendars(collect); 13 | } 14 | 15 | public com.softwarearchetypes.availability.Calendar get(ResourceId resourceId) { 16 | return calendars.getOrDefault(resourceId, Calendar.empty(resourceId)); 17 | } 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/application/OverdueLockHandling.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.application; 2 | 3 | import org.springframework.scheduling.annotation.Scheduled; 4 | 5 | import com.softwarearchetypes.availability.domain.AssetAvailabilityRepository; 6 | 7 | class OverdueLockHandling { 8 | 9 | private final AvailabilityService availabilityService; 10 | private final AssetAvailabilityRepository repository; 11 | 12 | OverdueLockHandling(AvailabilityService availabilityService, AssetAvailabilityRepository repository) { 13 | this.availabilityService = availabilityService; 14 | this.repository = repository; 15 | } 16 | 17 | @Scheduled(fixedDelay = 10) 18 | void unlockOverdue() { 19 | repository 20 | .findOverdue() 21 | .forEach(availabilityService::unlockIfOverdue); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /party/diagrams/party-addresses-aggregate-model.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 150 3 | skinparam linetype ortho 4 | 5 | object Party 6 | object PartyIdentifier { 7 | value: UUID 8 | } 9 | object Addresses 10 | object Address { 11 | validFrom: Date 12 | validTo: Date 13 | } 14 | object AddressId { 15 | value: UUID 16 | } 17 | object AddressUseType { 18 | value: String 19 | } 20 | object EmailAddress { 21 | value: String 22 | } 23 | object GeographicAddress { 24 | addressLine: String[] 25 | city: String 26 | region: String 27 | zipCode: String 28 | } 29 | object WebPageAddress { 30 | url: String 31 | } 32 | 33 | Party "1" *- "1" PartyIdentifier 34 | Party "1" *-- "0..1" Addresses 35 | Addresses "1" --- "0..*" Address 36 | Address "1" *-- "1..*" AddressUseType 37 | Address "1" *-- "1*" AddressId 38 | 39 | EmailAddress --up-|> Address 40 | GeographicAddress --up-|> Address 41 | WebPageAddress --up-|> Address 42 | @enduml -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/Balances.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | import java.util.Set; 6 | 7 | import com.softwarearchetypes.quantity.money.Money; 8 | 9 | public record Balances(Map balances) { 10 | 11 | public static Balances empty() { 12 | return new Balances(Map.of()); 13 | } 14 | 15 | public Optional get(AccountId accountId) { 16 | return Optional.ofNullable(balances.get(accountId)); 17 | } 18 | 19 | public Money sum() { 20 | return balances 21 | .values() 22 | .stream() 23 | .reduce(Money.zeroPln(), Money::add); 24 | } 25 | 26 | public int size() { 27 | return balances.size(); 28 | } 29 | 30 | public Set accounts() { 31 | return balances().keySet(); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/Calendar.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public record Calendar(ResourceId resourceId, 8 | Map> calendar) { 9 | 10 | public static Calendar withAvailableSlots(ResourceId resourceId, TimeSlot... availableSlots) { 11 | return new Calendar(resourceId, Map.of(Owner.none(), List.of(availableSlots))); 12 | } 13 | 14 | static Calendar empty(ResourceId resourceId) { 15 | return new Calendar(resourceId, new HashMap<>()); 16 | } 17 | 18 | public List availableSlots() { 19 | return calendar.getOrDefault(Owner.none(), List.of()); 20 | } 21 | 22 | public List takenBy(Owner requester) { 23 | return calendar.getOrDefault(requester, List.of()); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/car-with-booleans.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 100 3 | skinparam linetype ortho 4 | 5 | object Car { 6 | - id: CarId 7 | - reserved: boolean 8 | - inMaintenance: boolean 9 | - inRelocation: boolean 10 | - licensePlate: LicensePlate 11 | - mileage: Mileage 12 | __ 13 | + isReserved(): boolean 14 | + isInMaintenance(): boolean 15 | + isInRelocation(): boolean 16 | + reserve(): boolean 17 | + enterMaintenance(): boolean 18 | + registerRelocation(): boolean 19 | + cancelReservation(): void 20 | } 21 | 22 | object CarService { 23 | - carRepository: CarRepository 24 | __ 25 | + reserve(carId: CarId): boolean 26 | + enterMaintenance(carId: CarId): boolean 27 | + registerRelocation(carId: CarId): boolean 28 | } 29 | 30 | object CarRepository { 31 | + findById(carId: CarId): Car 32 | + save(car: Car): void 33 | } 34 | 35 | CarService --> Car 36 | CarService --> CarRepository 37 | 38 | @enduml -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/MetaData.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public record MetaData(Map metadata) { 7 | 8 | public static final MetaData EMPTY = new MetaData(Map.of()); 9 | 10 | static MetaData empty() { 11 | return EMPTY; 12 | } 13 | 14 | static MetaData of(Map metadata) { 15 | return metadata != null ? new MetaData(metadata) : EMPTY; 16 | } 17 | 18 | static MetaData of(String... keyValues) { 19 | if (keyValues.length % 2 != 0) { 20 | throw new IllegalArgumentException("MetaData must have even number of elements (key-value pairs)."); 21 | } 22 | Map map = new HashMap<>(); 23 | for (int i = 0; i < keyValues.length; i += 2) { 24 | map.put(keyValues[i], keyValues[i + 1]); 25 | } 26 | return new MetaData(map); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /availability/simple-availability/src/test/groovy/com/softwarearchetypes/availability/application/InMemoryAssetAvailabilityRepository.groovy: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.application 2 | 3 | import com.softwarearchetypes.availability.domain.AssetAvailability 4 | import com.softwarearchetypes.availability.domain.AssetAvailabilityRepository 5 | import com.softwarearchetypes.availability.domain.AssetId 6 | 7 | import java.util.stream.Stream 8 | 9 | class InMemoryAssetAvailabilityRepository implements AssetAvailabilityRepository { 10 | 11 | Map content = [:] 12 | 13 | @Override 14 | void save(AssetAvailability assetAvailability) { 15 | content.put(assetAvailability.id(), assetAvailability) 16 | } 17 | 18 | @Override 19 | Optional findBy(AssetId assetId) { 20 | Optional.ofNullable(content[assetId]) 21 | } 22 | 23 | @Override 24 | Stream findOverdue() { 25 | null 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ProductInstanceId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Unique identifier for a ProductInstance. 7 | * 8 | * ProductInstance needs its own identifier because: 9 | * - SerialNumber is optional (some instances are tracked only by Batch) 10 | * - Batch is optional (some instances have only SerialNumber) 11 | * - At least one of them must exist, but they serve different business purposes 12 | * - We need a consistent primary key for database persistence regardless of which tracking method is used 13 | */ 14 | record ProductInstanceId(UUID value) { 15 | 16 | static ProductInstanceId newOne() { 17 | return new ProductInstanceId(UUID.randomUUID()); 18 | } 19 | 20 | static ProductInstanceId of(String value) { 21 | return new ProductInstanceId(UUID.fromString(value)); 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return value.toString(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/AccountView.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.time.Instant; 4 | import java.util.List; 5 | 6 | import com.softwarearchetypes.quantity.money.Money; 7 | 8 | import static java.util.stream.Collectors.toList; 9 | 10 | public record AccountView(AccountId id, String name, String type, Money balance, List entries) { 11 | 12 | //intentionally left package private 13 | static AccountView from(Account account) { 14 | List entryViews = account.entries().stream().map(EntryView::from).collect(toList()); 15 | return new AccountView(account.id(), account.name(), account.type().name(), account.balance(), entryViews); 16 | } 17 | 18 | Money balanceAsOf(Instant time) { 19 | return entries 20 | .stream() 21 | .filter(e -> !e.appliesAt().isAfter(time)) 22 | .map(EntryView::amount) 23 | .reduce(Money.zeroPln(), Money::add); 24 | } 25 | } -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/commands/Command.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.commands; 2 | 3 | import com.fasterxml.jackson.annotation.JsonSubTypes; 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 | 6 | import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME; 7 | 8 | @JsonTypeInfo(property = "type", use = NAME) 9 | @JsonSubTypes({ 10 | @JsonSubTypes.Type(value = Register.class, name = Register.TYPE), 11 | @JsonSubTypes.Type(value = Activate.class, name = Activate.TYPE), 12 | @JsonSubTypes.Type(value = Withdraw.class, name = Withdraw.TYPE), 13 | @JsonSubTypes.Type(value = Lock.class, name = Lock.TYPE), 14 | @JsonSubTypes.Type(value = LockIndefinitely.class, name = LockIndefinitely.TYPE), 15 | @JsonSubTypes.Type(value = Unlock.class, name = Unlock.TYPE) 16 | }) 17 | public sealed interface Command permits Register, Activate, Withdraw, Lock, LockIndefinitely, Unlock { 18 | 19 | String getType(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/Company.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Set; 4 | 5 | import com.softwarearchetypes.common.Version; 6 | import com.softwarearchetypes.party.events.CompanyRegistered; 7 | import com.softwarearchetypes.party.events.PartyRegistered; 8 | 9 | import static java.util.stream.Collectors.toSet; 10 | 11 | public final class Company extends Organization { 12 | 13 | Company(PartyId partyId, OrganizationName organizationName, Set roles, 14 | Set registeredIdentifiers, Version version) { 15 | super(partyId, organizationName, roles, registeredIdentifiers, version); 16 | } 17 | 18 | @Override 19 | PartyRegistered toPartyRegisteredEvent() { 20 | return new CompanyRegistered(id().asString(), organizationName().value(), 21 | registeredIdentifiers().stream().map(RegisteredIdentifier::asString).collect(toSet()), 22 | roles().stream().map(Role::asString).collect(toSet())); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/TransactionType.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | //payment_received, payment_sent, accrual, internal_transfer, provision, reversal, opening_balance 6 | //todo: maybe enum 7 | public record TransactionType(@JsonValue String value) { 8 | 9 | public static final TransactionType INITIALIZATION = new TransactionType("initialization"); 10 | public static final TransactionType REVERSAL = new TransactionType("reversal"); 11 | public static final TransactionType TRANSFER = new TransactionType("transfer"); 12 | public static final TransactionType REALLOCATION = new TransactionType("reallocation"); 13 | public static final TransactionType EXPIRATION_COMPENSATION = new TransactionType("expiration_compensation"); 14 | 15 | static TransactionType of(String value) { 16 | return new TransactionType(value); 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/OrganizationUnit.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Set; 4 | 5 | import com.softwarearchetypes.common.Version; 6 | import com.softwarearchetypes.party.events.OrganizationUnitRegistered; 7 | import com.softwarearchetypes.party.events.PartyRegistered; 8 | 9 | import static java.util.stream.Collectors.toSet; 10 | 11 | public final class OrganizationUnit extends Organization { 12 | 13 | OrganizationUnit(PartyId partyId, OrganizationName organizationName, Set roles, 14 | Set registeredIdentifiers, Version version) { 15 | super(partyId, organizationName, roles, registeredIdentifiers, version); 16 | } 17 | 18 | @Override 19 | PartyRegistered toPartyRegisteredEvent() { 20 | return new OrganizationUnitRegistered(id().asString(), organizationName().value(), 21 | registeredIdentifiers().stream().map(RegisteredIdentifier::asString).collect(toSet()), 22 | roles().stream().map(Role::asString).collect(toSet())); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PersonalIdentificationNumber.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import static java.util.Optional.ofNullable; 6 | 7 | record PersonalIdentificationNumber(String value) implements RegisteredIdentifier { 8 | 9 | private static final Pattern PATTERN = Pattern.compile("\\d{11}"); 10 | //can be any other pattern 11 | private static final String TYPE = "PERSONAL_IDENTIFICATION_NUMBER"; 12 | 13 | PersonalIdentificationNumber { 14 | if (ofNullable(value).filter(it -> PATTERN.matcher(it).matches()).isEmpty()) { 15 | throw new IllegalArgumentException("Personal identification number does not meet syntax criteria"); 16 | } 17 | } 18 | 19 | static PersonalIdentificationNumber of(String value) { 20 | return new PersonalIdentificationNumber(value); 21 | } 22 | 23 | @Override 24 | public String type() { 25 | return TYPE; 26 | } 27 | 28 | @Override 29 | public String asString() { 30 | return value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/TextualSerialNumber.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | 5 | /** 6 | * TextualSerialNumber is a simple string-based serial number without special validation. 7 | * 8 | * Use this when: 9 | * - No industry-specific format is required 10 | * - You have your own internal numbering scheme 11 | * - The serial number is just a unique string 12 | * 13 | * Examples: "HYP/2024/00123", "CONS-2024-001", "PKG-2024-XYZ789" 14 | */ 15 | record TextualSerialNumber(String value) implements SerialNumber { 16 | 17 | TextualSerialNumber { 18 | checkArgument(value != null && !value.isBlank(), 19 | "SerialNumber cannot be null or blank"); 20 | } 21 | 22 | static TextualSerialNumber of(String value) { 23 | return new TextualSerialNumber(value); 24 | } 25 | 26 | @Override 27 | public String type() { 28 | return "TEXTUAL"; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return value; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartyRoleFactory.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import com.softwarearchetypes.common.Result; 4 | import com.softwarearchetypes.party.events.PartyRoleDefinitionFailed; 5 | 6 | import static com.softwarearchetypes.party.events.PartyRoleDefinitionFailed.dueToPoliciesNotMet; 7 | 8 | class PartyRoleFactory { 9 | 10 | private static final PartyRoleDefiningPolicy DEFAULT_PARTY_ROLE_DEFINING_POLICY = new AlwaysAllowPartyRoleDefiningPolicy(); 11 | 12 | private final PartyRoleDefiningPolicy policy; 13 | 14 | PartyRoleFactory(PartyRoleDefiningPolicy policy) { 15 | this.policy = policy != null ? policy : DEFAULT_PARTY_ROLE_DEFINING_POLICY; 16 | } 17 | 18 | PartyRoleFactory() { 19 | this(null); 20 | } 21 | 22 | Result defineFor(Party party, Role role) { 23 | if (policy.canDefineFor(party, role)) { 24 | return Result.success(PartyRole.of(party.id(), role)); 25 | } else { 26 | return Result.failure(dueToPoliciesNotMet()); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.softwarearchetypes 6 | archetypes 7 | 0.0.1 8 | pom 9 | 10 | archetypes 11 | Archetypes 12 | 13 | 14 | 21 15 | 16 | 17 | 18 | availability/timed-availability 19 | availability/simple-availability 20 | general-assignment 21 | waitlist 22 | configurator 23 | accounting 24 | common 25 | quantity 26 | pricing 27 | product 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/Unconstrained.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | 5 | /** 6 | * No constraints - any value of the specified type is valid. 7 | * Example: any text for a free-form comment field 8 | * 9 | * Persistence config example: {} (empty) 10 | */ 11 | class Unconstrained implements FeatureValueConstraint { 12 | 13 | private final FeatureValueType valueType; 14 | 15 | Unconstrained(FeatureValueType valueType) { 16 | checkArgument(valueType != null, "Value type must be defined"); 17 | this.valueType = valueType; 18 | } 19 | 20 | @Override 21 | public FeatureValueType valueType() { 22 | return valueType; 23 | } 24 | 25 | @Override 26 | public String type() { 27 | return "UNCONSTRAINED"; 28 | } 29 | 30 | @Override 31 | public boolean isValid(Object value) { 32 | return valueType.isInstance(value); 33 | } 34 | 35 | @Override 36 | public String desc() { 37 | return "any " + valueType.name().toLowerCase(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/calendar-per-resource.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 100 3 | skinparam linetype ortho 4 | 5 | object AvailabilityFacade { 6 | + block(resourceId: ResourceId, timeSlot: TimeSlot, requester: Owner): boolean 7 | + release(resourceId: ResourceId, timeSlot: TimeSlot, requester: Owner): boolean 8 | } 9 | 10 | object ResourceAvailability { 11 | - resourceId: ResourceId 12 | - blockades: List 13 | __ 14 | + block(timeSlot: TimeSlot, requester: Owner): void 15 | + release(timeSlot: TimeSlot, requester: Owner): void 16 | } 17 | 18 | object Blockade { 19 | + timeSlot: TimeSlot 20 | + owner: Owner 21 | } 22 | 23 | object Owner { 24 | + value: UUID 25 | __ 26 | + of(value: UUID): Owner 27 | } 28 | 29 | object ResourceId { 30 | + value: UUID 31 | __ 32 | + of(value: UUID): ResourceId 33 | } 34 | 35 | object TimeSlot { 36 | + from: Instant 37 | + to: Instant 38 | } 39 | 40 | AvailabilityFacade ..> ResourceAvailability : «loads» 41 | ResourceAvailability "1" *-- "0..*" Blockade 42 | ResourceAvailability --> ResourceId 43 | Blockade --> TimeSlot 44 | Blockade --> Owner 45 | 46 | @enduml -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/TransactionBuilderFactory.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.time.Clock; 4 | 5 | public class TransactionBuilderFactory { 6 | 7 | private final AccountRepository accountRepository; 8 | private final TransactionRepository transactionRepository; 9 | private final EntryAllocations entryAllocations; 10 | private final EntryRepository entryRepository; 11 | private final Clock clock; 12 | 13 | TransactionBuilderFactory(AccountRepository accountRepository, TransactionRepository transactionRepository, EntryAllocations entryAllocations, EntryRepository entryRepository, Clock clock) { 14 | this.accountRepository = accountRepository; 15 | this.transactionRepository = transactionRepository; 16 | this.entryAllocations = entryAllocations; 17 | this.entryRepository = entryRepository; 18 | this.clock = clock; 19 | } 20 | 21 | public TransactionBuilder transaction() { 22 | return new TransactionBuilder(accountRepository, transactionRepository, this.entryAllocations, this.entryRepository, this.clock); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/InMemoryAddressesRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.HashSet; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import java.util.function.Predicate; 8 | 9 | import static java.util.stream.Collectors.toList; 10 | 11 | class InMemoryAddressesRepository implements AddressesRepository { 12 | 13 | private ConcurrentHashMap map = new ConcurrentHashMap<>(10); 14 | 15 | @Override 16 | public Optional findFor(PartyId partyId) { 17 | return Optional.ofNullable(map.get(partyId)); 18 | } 19 | 20 | @Override 21 | public List
findMatching(PartyId partyId, Predicate
predicate) { 22 | return findFor(partyId).map(Addresses::asSet).orElse(new HashSet<>()) 23 | .stream() 24 | .filter(predicate) 25 | .collect(toList()); 26 | } 27 | 28 | @Override 29 | public void save(Addresses addresses) { 30 | map.put(addresses.partyId(), addresses); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/AccountName.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.Arrays; 4 | 5 | import com.softwarearchetypes.common.StringUtils; 6 | 7 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 8 | 9 | record AccountName(String value) { 10 | 11 | final static String DEFAULT_DELIMITER = ":"; 12 | 13 | AccountName { 14 | checkArgument(StringUtils.isNotBlank(value), "Account name cannot be empty"); 15 | } 16 | 17 | static AccountName of(String value) { 18 | return new AccountName(value); 19 | } 20 | 21 | static AccountName compositeFrom(String... components) { 22 | return compositeFrom(DEFAULT_DELIMITER, components); 23 | } 24 | 25 | static AccountName compositeFrom(String delimiter, String... components) { 26 | checkArgument(components != null && components.length > 0, "Account name cannot be built from an empty array"); 27 | Arrays.stream(components).forEach(val -> checkArgument(StringUtils.isNotBlank(val), "Account name component cannot be empty")); 28 | return new AccountName(String.join(delimiter, components)); 29 | } 30 | } -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PartiesTestEventListener.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Optional; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.LinkedBlockingQueue; 6 | import java.util.function.Predicate; 7 | 8 | import com.softwarearchetypes.party.events.InMemoryEventsPublisher; 9 | import com.softwarearchetypes.party.events.PublishedEvent; 10 | 11 | class PartiesTestEventListener implements InMemoryEventsPublisher.InMemoryEventObserver { 12 | 13 | private final BlockingQueue events = new LinkedBlockingQueue<>(); 14 | 15 | PartiesTestEventListener(InMemoryEventsPublisher eventsPublisher) { 16 | eventsPublisher.register(this); 17 | } 18 | 19 | @Override 20 | public void handle(PublishedEvent event) { 21 | events.add(event); 22 | } 23 | 24 | Optional findMatching(Predicate predicate) { 25 | return events.stream().filter(predicate).findFirst(); 26 | } 27 | 28 | boolean thereIsAnEventEqualTo(PublishedEvent expectedEvent) { 29 | return findMatching(it -> it.equals(expectedEvent)).isPresent(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/events/AssetWithdrawn.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | import com.softwarearchetypes.availability.domain.AssetId; 7 | import com.fasterxml.jackson.annotation.JsonCreator; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | 10 | public class AssetWithdrawn extends BaseDomainEvent { 11 | 12 | @JsonIgnore 13 | static final String TYPE = "AssetWithdrawn"; 14 | 15 | private final String assetId; 16 | 17 | private AssetWithdrawn(String assetId) { 18 | super(); 19 | this.assetId = assetId; 20 | } 21 | 22 | @JsonCreator 23 | private AssetWithdrawn(UUID id, Instant occurredAt, String assetId) { 24 | super(id, occurredAt); 25 | this.assetId = assetId; 26 | } 27 | 28 | public static AssetWithdrawn from(AssetId assetId) { 29 | return new AssetWithdrawn(assetId.asString()); 30 | } 31 | 32 | @Override 33 | public String getType() { 34 | return TYPE; 35 | } 36 | 37 | public String getAssetId() { 38 | return assetId; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/segment/SegmentInMinutes.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.segment; 2 | 3 | 4 | public record SegmentInMinutes(int value) { 5 | 6 | public static SegmentInMinutes of(int minutes, int slotDurationInMinutes) { 7 | if (minutes <= 0) { 8 | throw new IllegalArgumentException("SegmentInMinutesDuration must be positive"); 9 | } 10 | if (minutes < slotDurationInMinutes) { 11 | throw new IllegalArgumentException("SegmentInMinutesDuration must be at least " + slotDurationInMinutes + " minutes"); 12 | } 13 | if (minutes % slotDurationInMinutes != 0) { 14 | throw new IllegalArgumentException("SegmentInMinutesDuration must be a multiple of " + slotDurationInMinutes + " minutes"); 15 | } 16 | return new SegmentInMinutes(minutes); 17 | } 18 | 19 | public static SegmentInMinutes of(int minutes) { 20 | return of(minutes, Segments.DEFAULT_SEGMENT_DURATION_IN_MINUTES); 21 | } 22 | 23 | public static SegmentInMinutes defaultSegment() { 24 | return of(Segments.DEFAULT_SEGMENT_DURATION_IN_MINUTES); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/InMemoryPostingRuleRepository.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | 8 | class InMemoryPostingRuleRepository implements PostingRuleRepository { 9 | 10 | private final Map rules = new HashMap<>(); 11 | 12 | @Override 13 | public List findAll() { 14 | return List.copyOf(rules.values()); 15 | } 16 | 17 | @Override 18 | public Optional find(PostingRuleId id) { 19 | return Optional.ofNullable(rules.get(id)); 20 | } 21 | 22 | @Override 23 | public void save(PostingRule rule) { 24 | rules.put(rule.id(), rule); 25 | } 26 | 27 | @Override 28 | public void delete(PostingRuleId id) { 29 | rules.remove(id); 30 | } 31 | 32 | @Override 33 | public List findEligibleRules(PostingContext context) { 34 | return rules.values() 35 | .stream() 36 | .filter(rule -> rule.isEligible(context)) 37 | .toList(); 38 | } 39 | } -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/events/AssetLockExpired.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | import com.softwarearchetypes.availability.domain.AssetId; 7 | import com.fasterxml.jackson.annotation.JsonCreator; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | 10 | public class AssetLockExpired extends BaseDomainEvent { 11 | 12 | @JsonIgnore 13 | static final String TYPE = "AssetLockExpired"; 14 | 15 | private final String assetId; 16 | 17 | private AssetLockExpired(String assetId) { 18 | super(); 19 | this.assetId = assetId; 20 | } 21 | 22 | @JsonCreator 23 | private AssetLockExpired(UUID id, Instant occurredAt, String assetId) { 24 | super(id, occurredAt); 25 | this.assetId = assetId; 26 | } 27 | 28 | public static AssetLockExpired from(AssetId assetId) { 29 | return new AssetLockExpired(assetId.asString()); 30 | } 31 | 32 | @Override 33 | public String getType() { 34 | return TYPE; 35 | } 36 | 37 | String getAssetId() { 38 | return assetId; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/events/AssetRegistered.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | import com.softwarearchetypes.availability.domain.AssetId; 7 | import com.fasterxml.jackson.annotation.JsonCreator; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | 10 | public class AssetRegistered extends BaseDomainEvent { 11 | 12 | @JsonIgnore 13 | static final String TYPE = "AssetRegistered"; 14 | 15 | private final String assetId; 16 | 17 | private AssetRegistered(String assetId) { 18 | super(); 19 | this.assetId = assetId; 20 | } 21 | 22 | @JsonCreator 23 | private AssetRegistered(UUID id, Instant occurredAt, String assetId) { 24 | super(id, occurredAt); 25 | this.assetId = assetId; 26 | } 27 | 28 | public static AssetRegistered from(AssetId assetId) { 29 | return new AssetRegistered(assetId.asString()); 30 | } 31 | 32 | @Override 33 | public String getType() { 34 | return TYPE; 35 | } 36 | 37 | public String getAssetId() { 38 | return assetId; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /general-assignment/src/main/java/softwarearchetypes/multidimensionalknapsack/TotalCapacity.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.multidimensionalknapsack; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | 9 | public record TotalCapacity(List capacities) { 10 | 11 | public static TotalCapacity of(CapacityDimension... capacities) { 12 | return new TotalCapacity(Arrays.asList(capacities)); 13 | } 14 | 15 | public static TotalCapacity of(List capacities) { 16 | return new TotalCapacity(capacities); 17 | } 18 | 19 | static TotalCapacity zero() { 20 | return new TotalCapacity(List.of()); 21 | } 22 | 23 | int size() { 24 | return capacities.size(); 25 | } 26 | 27 | public List capacities() { 28 | return new ArrayList<>(capacities); 29 | } 30 | 31 | public TotalCapacity add(List capacities) { 32 | List newCapacities = new ArrayList<>(this.capacities); 33 | newCapacities.addAll(capacities); 34 | return new TotalCapacity(new ArrayList<>(newCapacities)); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /availability/timed-availability/diagrams/calendar-per-resource-per-time-period.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam MinClassWidth 100 3 | skinparam linetype ortho 4 | 5 | object AvailabilityFacade { 6 | + block(resourceId: ResourceId, timeSlot: TimeSlot, owner: Owner): boolean 7 | + release(resourceId: ResourceId, timeSlot: TimeSlot, owner: Owner): boolean 8 | } 9 | 10 | object ResourceAvailability { 11 | - resourceId: ResourceId 12 | - blockades: List 13 | - period: TimeSlot 14 | __ 15 | + block(timeSlot: TimeSlot, owner: Owner): void 16 | + release(timeSlot: TimeSlot, owner: Owner): void 17 | } 18 | 19 | object Blockade { 20 | + timeSlot: TimeSlot 21 | + owner: Owner 22 | } 23 | 24 | object Owner { 25 | + value: UUID 26 | __ 27 | + of(value: UUID): Owner 28 | } 29 | 30 | object ResourceId { 31 | + value: UUID 32 | __ 33 | + of(value: UUID): ResourceId 34 | } 35 | 36 | object TimeSlot { 37 | + from: Instant 38 | + to: Instant 39 | } 40 | 41 | AvailabilityFacade ..> ResourceAvailability : «loads» 42 | ResourceAvailability "1" *-- "0..*" Blockade 43 | ResourceAvailability --> ResourceId 44 | ResourceAvailability --> TimeSlot 45 | Blockade --> TimeSlot 46 | Blockade --> Owner 47 | 48 | @enduml -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ServiceDeliveryStatus.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | /** 4 | * Records the status of the delivery of a particular ServiceInstance. 5 | * 6 | * ServiceInstances are executions of a process, with a lifecycle: 7 | * SCHEDULED → EXECUTING → COMPLETED/CANCELLED 8 | */ 9 | enum ServiceDeliveryStatus { 10 | 11 | /** 12 | * The ServiceInstance has been scheduled for delivery. 13 | */ 14 | SCHEDULED, 15 | 16 | /** 17 | * The ServiceInstance is currently in the process of delivery. 18 | */ 19 | EXECUTING, 20 | 21 | /** 22 | * The delivery of the ServiceInstance has been completed successfully. 23 | */ 24 | COMPLETED, 25 | 26 | /** 27 | * The ServiceInstance has been cancelled before or during execution. 28 | */ 29 | CANCELLED; 30 | 31 | boolean isFinished() { 32 | return this == COMPLETED || this == CANCELLED; 33 | } 34 | 35 | boolean isInProgress() { 36 | return this == EXECUTING; 37 | } 38 | 39 | boolean canStart() { 40 | return this == SCHEDULED; 41 | } 42 | 43 | boolean canCancel() { 44 | return this == SCHEDULED || this == EXECUTING; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/EntryView.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.time.Instant; 4 | 5 | import com.softwarearchetypes.quantity.money.Money; 6 | 7 | public record EntryView(EntryId entryId, 8 | EntryType type, 9 | Money amount, 10 | TransactionId transactionId, 11 | AccountId accountId, 12 | Instant occurredAt, 13 | Instant appliesAt) { 14 | 15 | //intentionally left package-scoped 16 | static EntryView from(Entry entry) { 17 | return new EntryView(entry.id(), 18 | EntryType.from(entry), 19 | entry.amount(), 20 | entry.transactionId(), 21 | entry.accountId(), 22 | entry.occurredAt(), 23 | entry.appliesAt()); 24 | } 25 | 26 | public enum EntryType { 27 | CREDIT, 28 | DEBIT; 29 | 30 | static EntryType from(Entry entry) { 31 | return switch (entry) { 32 | case AccountCredited c -> CREDIT; 33 | case AccountDebited d -> DEBIT; 34 | }; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/RegisteredIdentifierFixture.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.Set; 4 | import java.util.stream.IntStream; 5 | 6 | import static java.util.stream.Collectors.toSet; 7 | import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; 8 | 9 | final class RegisteredIdentifierFixture { 10 | 11 | static String someType() { 12 | return randomAlphabetic(10); 13 | } 14 | 15 | static String someValue() { 16 | return randomAlphabetic(10); 17 | } 18 | 19 | static RegisteredIdentifier someRegisteredIdentifier() { 20 | return new RegisteredIdentifier() { 21 | 22 | private static final String TYPE = someType(); 23 | private static final String VALUE = someValue(); 24 | 25 | @Override 26 | public String type() { 27 | return TYPE; 28 | } 29 | 30 | @Override 31 | public String asString() { 32 | return VALUE; 33 | } 34 | }; 35 | } 36 | 37 | static Set someIdentifierSetOfSize(int size) { 38 | return IntStream.range(0, size).mapToObj(it -> someRegisteredIdentifier()).collect(toSet()); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /party/src/main/java/com/softwarearchetypes/party/PartiesQueries.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.function.Predicate; 6 | 7 | import static java.lang.String.format; 8 | 9 | public class PartiesQueries { 10 | 11 | private final PartyRepository partyRepository; 12 | 13 | PartiesQueries(PartyRepository partyRepository) { 14 | this.partyRepository = partyRepository; 15 | } 16 | 17 | public Optional findBy(PartyId partyId) { 18 | return partyRepository.findBy(partyId); 19 | } 20 | 21 | public Optional findOneBy(RegisteredIdentifier registeredIdentifier) { 22 | List partiesMatching = partyRepository.findBy(registeredIdentifier); 23 | if (partiesMatching.size() > 1) { 24 | throw new IllegalStateException(format("There are more than one parties with the same registered identifier of %s", registeredIdentifier)); 25 | } 26 | return partiesMatching.stream().findFirst(); 27 | } 28 | 29 | public List findMatching(Predicate predicate) { 30 | return partyRepository.findMatching(predicate); 31 | } 32 | 33 | //find by Id 34 | //find by identity 35 | //find by role 36 | //etc 37 | } 38 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PartyIdTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.UUID; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static org.junit.jupiter.api.Assertions.*; 8 | 9 | class PartyIdTest { 10 | 11 | @Test 12 | void twoPartyIdsShouldNotBeEqualWhenCreatedForDifferentValues() { 13 | //given 14 | PartyId firstPartyId = PartyId.of(UUID.randomUUID()); 15 | PartyId secondPartyId = PartyId.of(UUID.randomUUID()); 16 | 17 | //expect 18 | assertNotEquals(firstPartyId, secondPartyId); 19 | } 20 | 21 | @Test 22 | void twoPartyIdsShouldBeEqualWhenCreatedForTheSameValue() { 23 | //given 24 | UUID value = UUID.randomUUID(); 25 | 26 | //expect 27 | assertEquals(PartyId.of(value), PartyId.of(value)); 28 | } 29 | 30 | @Test 31 | void partyIdIsConvertibleToTheValueItWasCreatedFrom() { 32 | //given 33 | UUID value = UUID.randomUUID(); 34 | PartyId partyId = PartyId.of(value); 35 | 36 | //expect 37 | assertEquals(value.toString(), partyId.asString()); 38 | } 39 | 40 | @Test 41 | void shouldNotAllowToCreatePartyIdForNullValue() { 42 | //expect 43 | assertThrows(IllegalArgumentException.class, () -> PartyId.of(null)); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/AddressIdTest.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.UUID; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static org.junit.jupiter.api.Assertions.*; 8 | 9 | class AddressIdTest { 10 | 11 | @Test 12 | void twoAddressIdsShouldNotBeEqualWhenCreatedForDifferentValues() { 13 | //given 14 | AddressId firstAddressId = AddressId.of(UUID.randomUUID()); 15 | AddressId secondAddressId = AddressId.of(UUID.randomUUID()); 16 | 17 | //expect 18 | assertNotEquals(firstAddressId, secondAddressId); 19 | } 20 | 21 | @Test 22 | void twoAddressIdsShouldBeEqualWhenCreatedForTheSameValue() { 23 | //given 24 | UUID value = UUID.randomUUID(); 25 | 26 | //expect 27 | assertEquals(AddressId.of(value), AddressId.of(value)); 28 | } 29 | 30 | @Test 31 | void AddressIdIsConvertibleToTheValueItWasCreatedFrom() { 32 | //given 33 | UUID value = UUID.randomUUID(); 34 | AddressId addressId = AddressId.of(value); 35 | 36 | //expect 37 | assertEquals(value.toString(), addressId.asString()); 38 | } 39 | 40 | @Test 41 | void shouldNotAllowToCreateAddressIdForNullValue() { 42 | //expect 43 | assertThrows(IllegalArgumentException.class, () -> AddressId.of(null)); 44 | } 45 | } -------------------------------------------------------------------------------- /availability/timed-availability/src/main/java/com/softwarearchetypes/availability/ResourceId.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability; 2 | 3 | import jakarta.persistence.Embeddable; 4 | 5 | import java.io.Serializable; 6 | import java.util.Objects; 7 | import java.util.UUID; 8 | 9 | @Embeddable 10 | public class ResourceId implements Serializable { 11 | 12 | public static ResourceId newOne() { 13 | return new ResourceId(UUID.randomUUID()); 14 | } 15 | 16 | private UUID id; 17 | 18 | public ResourceId(UUID uuid) { 19 | this.id = uuid; 20 | } 21 | 22 | public ResourceId() { 23 | } 24 | 25 | public static ResourceId none() { 26 | return new ResourceId(null); 27 | } 28 | 29 | public static ResourceId of(String id) { 30 | if (id == null) { 31 | return none(); 32 | } 33 | return new ResourceId(UUID.fromString(id)); 34 | } 35 | 36 | public UUID getId() { 37 | return id; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object o) { 42 | if (this == o) return true; 43 | if (o == null || getClass() != o.getClass()) return false; 44 | ResourceId resourceId = (ResourceId) o; 45 | return Objects.equals(resourceId.id, this.id); 46 | } 47 | 48 | @Override 49 | public int hashCode() { 50 | return Objects.hash(id); 51 | } 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /party/src/test/java/com/softwarearchetypes/party/PartyAbstractTestDataBuilder.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.party; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import com.softwarearchetypes.common.Version; 7 | 8 | sealed abstract class PartyAbstractTestDataBuilder permits CompanyTestDataBuilder, OrganizationUnitTestDataBuilder, PersonTestDataBuilder { 9 | 10 | PartyId partyId; 11 | Set roles = new HashSet<>(); 12 | Set registeredIdentifiers = new HashSet<>(); 13 | Version version = Version.initial(); 14 | 15 | PartyAbstractTestDataBuilder withRandomPartyId() { 16 | partyId = PartyId.random(); 17 | return this; 18 | } 19 | 20 | PartyAbstractTestDataBuilder with(Role role) { 21 | roles.add(role); 22 | return this; 23 | } 24 | 25 | PartyAbstractTestDataBuilder withRoleSetOf(Set roleSet) { 26 | roles.addAll(roleSet); 27 | return this; 28 | } 29 | 30 | PartyAbstractTestDataBuilder with(RegisteredIdentifier identifier) { 31 | registeredIdentifiers.add(identifier); 32 | return this; 33 | } 34 | 35 | PartyAbstractTestDataBuilder withRegisteredIdentifierSetOf(Set identifierSet) { 36 | registeredIdentifiers.addAll(identifierSet); 37 | return this; 38 | } 39 | 40 | abstract T build(); 41 | } 42 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/ProjectionAccount.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.util.function.Predicate; 4 | 5 | import com.softwarearchetypes.common.Version; 6 | 7 | class ProjectionAccount { 8 | 9 | //lock 10 | private AccountId accountId; 11 | //w bazie danych ten predicate to sql 12 | private Filter filter; 13 | private String name; 14 | private final Version version; 15 | 16 | ProjectionAccount(AccountId accountId, Filter filter, String name) { 17 | this(accountId, filter, name, Version.initial()); 18 | } 19 | 20 | ProjectionAccount(AccountId accountId, Filter filter, String name, Version version) { 21 | this.accountId = accountId; 22 | this.filter = filter; 23 | this.name = name; 24 | this.version = version; 25 | } 26 | 27 | String desc() { 28 | return name; 29 | } 30 | 31 | AccountId id() { 32 | return accountId; 33 | } 34 | 35 | Filter filter() { 36 | return filter; 37 | } 38 | 39 | Version version() { 40 | return version; 41 | } 42 | } 43 | 44 | 45 | //wrzucone w jedna klase, zeby latwiej bylo tlumaczyc na sql 46 | record Filter(Predicate entryFilter, Predicate accountFilter) { 47 | 48 | static Filter just(Predicate entryFilter) { 49 | return new Filter(entryFilter, account -> true); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /availability/timed-availability/src/test/java/com/softwarearchetypes/TestDbConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes; 2 | 3 | import org.springframework.boot.jdbc.DataSourceBuilder; 4 | import org.springframework.boot.test.context.TestConfiguration; 5 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.jdbc.core.JdbcTemplate; 8 | import org.testcontainers.containers.PostgreSQLContainer; 9 | 10 | import javax.sql.DataSource; 11 | 12 | @TestConfiguration(proxyBeanMethods = false) 13 | public class TestDbConfiguration { 14 | 15 | @Bean 16 | @ServiceConnection 17 | public PostgreSQLContainer postgreSQLContainer() { 18 | return new PostgreSQLContainer("postgres:15-alpine"); 19 | } 20 | 21 | @Bean 22 | JdbcTemplate jdbcTemplate(DataSource dataSource) { 23 | return new JdbcTemplate(dataSource); 24 | } 25 | 26 | @Bean 27 | public DataSource dataSource(PostgreSQLContainer postgres) { 28 | DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); 29 | dataSourceBuilder.username(postgres.getUsername()); 30 | dataSourceBuilder.password(postgres.getPassword()); 31 | dataSourceBuilder.driverClassName(postgres.getDriverClassName()); 32 | dataSourceBuilder.url(postgres.getJdbcUrl()); 33 | return dataSourceBuilder.build(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/Validity.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting; 2 | 3 | import java.time.Instant; 4 | 5 | /** 6 | * Represents a validity period for accounting entries. 7 | * validFrom is inclusive, validTo is exclusive [validFrom, validTo) 8 | */ 9 | public record Validity(Instant validFrom, Instant validTo) { 10 | 11 | public static final Validity ALWAYS = new Validity(Instant.EPOCH, Instant.MAX); 12 | 13 | public static Validity until(Instant validTo) { 14 | return new Validity(Instant.EPOCH, validTo); 15 | } 16 | 17 | public static Validity from(Instant validFrom) { 18 | return new Validity(validFrom, Instant.MAX); 19 | } 20 | 21 | public static Validity between(Instant validFrom, Instant validTo) { 22 | if (validFrom == null && validTo == null) { 23 | return ALWAYS; 24 | } 25 | if (validFrom == null) { 26 | return until(validTo); 27 | } 28 | if (validTo == null) { 29 | return from(validFrom); 30 | } 31 | return new Validity(validFrom, validTo); 32 | } 33 | 34 | public static Validity always() { 35 | return ALWAYS; 36 | } 37 | 38 | public boolean isValidAt(Instant instant) { 39 | return !instant.isBefore(validFrom) && instant.isBefore(validTo); 40 | } 41 | 42 | public boolean hasExpired(Instant instant) { 43 | return !instant.isBefore(validTo); 44 | } 45 | } -------------------------------------------------------------------------------- /product/src/main/java/com/softwarearchetypes/product/ProductFeatureTypeDefinition.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.product; 2 | 3 | import static com.softwarearchetypes.common.Preconditions.checkArgument; 4 | 5 | /** 6 | * Defines a product feature type along with whether it's mandatory or optional. 7 | */ 8 | class ProductFeatureTypeDefinition { 9 | 10 | private final ProductFeatureType featureType; 11 | private final boolean mandatory; 12 | 13 | ProductFeatureTypeDefinition(ProductFeatureType featureType, boolean mandatory) { 14 | checkArgument(featureType != null, "ProductFeatureType must be defined"); 15 | this.featureType = featureType; 16 | this.mandatory = mandatory; 17 | } 18 | 19 | static ProductFeatureTypeDefinition mandatory(ProductFeatureType featureType) { 20 | return new ProductFeatureTypeDefinition(featureType, true); 21 | } 22 | 23 | static ProductFeatureTypeDefinition optional(ProductFeatureType featureType) { 24 | return new ProductFeatureTypeDefinition(featureType, false); 25 | } 26 | 27 | ProductFeatureType featureType() { 28 | return featureType; 29 | } 30 | 31 | boolean isMandatory() { 32 | return mandatory; 33 | } 34 | 35 | boolean isOptional() { 36 | return !mandatory; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "%s(%s)".formatted(mandatory ? "mandatory" : "optional", featureType.name()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /configurator/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | softwarearchetypes 8 | configurator 9 | 1.0-SNAPSHOT 10 | 11 | 21 12 | 13 | 14 | 15 | org.junit.jupiter 16 | junit-jupiter-engine 17 | 5.10.2 18 | test 19 | 20 | 21 | org.assertj 22 | assertj-core 23 | 3.25.3 24 | test 25 | 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-compiler-plugin 32 | 33 | 21 34 | 21 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /accounting/src/main/java/com/softwarearchetypes/accounting/postingrules/AccountFinder.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.accounting.postingrules; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.softwarearchetypes.accounting.AccountView; 7 | import com.softwarearchetypes.accounting.AccountId; 8 | 9 | public interface AccountFinder { 10 | 11 | TargetAccounts findAccounts(PostingContext context); 12 | 13 | static AccountFinder fixed(String tag, AccountId accountId) { 14 | return context -> { 15 | AccountView account = context.accountingFacade() 16 | .findAccount(accountId) 17 | .orElseThrow(() -> new IllegalArgumentException("Account " + accountId + " not found")); 18 | return TargetAccounts.of(Map.of(tag, account)); 19 | }; 20 | } 21 | 22 | static AccountFinder fixed(Map accountIds) { 23 | return context -> { 24 | Map accounts = new HashMap<>(); 25 | for (Map.Entry entry : accountIds.entrySet()) { 26 | AccountView account = context.accountingFacade() 27 | .findAccount(entry.getValue()) 28 | .orElseThrow(() -> new IllegalArgumentException("Account " + entry.getValue() + " not found")); 29 | accounts.put(entry.getKey(), account); 30 | } 31 | return TargetAccounts.of(accounts); 32 | }; 33 | } 34 | } -------------------------------------------------------------------------------- /general-assignment/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | softwarearchetypes 8 | general-assignment 9 | 1.0-SNAPSHOT 10 | 11 | 21 12 | 13 | 14 | 15 | org.junit.jupiter 16 | junit-jupiter-engine 17 | 5.10.2 18 | test 19 | 20 | 21 | org.assertj 22 | assertj-core 23 | 3.25.3 24 | test 25 | 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-compiler-plugin 32 | 33 | 21 34 | 21 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /availability/simple-availability/src/main/java/com/softwarearchetypes/availability/events/AssetRegistrationRejected.java: -------------------------------------------------------------------------------- 1 | package com.softwarearchetypes.availability.events; 2 | 3 | import java.time.Instant; 4 | import java.util.UUID; 5 | 6 | import com.softwarearchetypes.availability.domain.AssetId; 7 | import com.fasterxml.jackson.annotation.JsonCreator; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | 10 | public class AssetRegistrationRejected extends BaseDomainEvent { 11 | 12 | @JsonIgnore 13 | static final String TYPE = "AssetRegistrationRejected"; 14 | 15 | private final String assetId; 16 | private final String reason; 17 | 18 | private AssetRegistrationRejected(String assetId, String reason) { 19 | super(); 20 | this.assetId = assetId; 21 | this.reason = reason; 22 | } 23 | 24 | @JsonCreator 25 | private AssetRegistrationRejected(UUID id, Instant occurredAt, String assetId, String reason) { 26 | super(id, occurredAt); 27 | this.assetId = assetId; 28 | this.reason = reason; 29 | } 30 | 31 | public static AssetRegistrationRejected dueToAlreadyExistingAssetWith(AssetId assetId) { 32 | return new AssetRegistrationRejected(assetId.asString(), "ASSET_ALREADY_EXISTS"); 33 | } 34 | 35 | @Override 36 | public String getType() { 37 | return TYPE; 38 | } 39 | 40 | String getAssetId() { 41 | return assetId; 42 | } 43 | 44 | String getReason() { 45 | return reason; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /configurator/src/main/java/softwarearchetypes/carconfig/OptionsRepository.java: -------------------------------------------------------------------------------- 1 | package softwarearchetypes.carconfig; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | class OptionsRepository { 9 | 10 | private final Map> options = new HashMap<>(); 11 | private final Map> rules = new HashMap<>(); 12 | 13 | List