You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/09/24 08:00:03 UTC
[isis] branch ISIS-2735-command-log updated: ISIS-2835: converts
jpa queries etc (wip)
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-2735-command-log
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/ISIS-2735-command-log by this push:
new 6ec66fb ISIS-2835: converts jpa queries etc (wip)
6ec66fb is described below
commit 6ec66fbb5adcdf1fabcd7e5c06b6e1177c1dac82
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Sep 24 08:59:51 2021 +0100
ISIS-2835: converts jpa queries etc (wip)
---
.../system/hooks/HasInteractionId_see-also.adoc | 2 +-
.../roles-mixins-contributees/contributee.adoc | 2 +-
.../applib/IsisModuleExtCommandLogApplib.java | 5 +-
.../commandlog/applib/app/CommandServiceMenu.java | 140 +++++
.../dom/PublishedCommandRepositoryAbstract.java | 7 +-
.../subscriptions/PublishedCommandSubscriber.java} | 63 ++-
.../jdo/src/main/java/META-INF/persistence.xml | 2 +-
.../commandlog/jdo/IsisModuleExtCommandLogJdo.java | 32 +-
.../PublishedCommand.java} | 182 +++---
.../PublishedCommandRepository.java} | 25 +-
.../commandlog/jdo/ui/CommandServiceMenu.java | 141 -----
.../commandlog/jpa/IsisModuleExtCommandLogJpa.java | 36 +-
.../commandlog/jpa/dom/PublishedCommand.java | 504 +++++++++++++++++
.../jpa/dom/PublishedCommandRepository.java} | 27 +-
.../commandlog/jpa/entities/CommandJpa.java | 620 ---------------------
.../jpa/entities/CommandJpaRepository.java | 323 -----------
.../secman/jdo/role/dom/ApplicationRole.java | 35 +-
.../pages/hints-and-tips/jdoql-and-timestamps.adoc | 2 +-
18 files changed, 871 insertions(+), 1277 deletions(-)
diff --git a/antora/components/refguide-index/modules/applib/pages/index/mixins/system/hooks/HasInteractionId_see-also.adoc b/antora/components/refguide-index/modules/applib/pages/index/mixins/system/hooks/HasInteractionId_see-also.adoc
index e473ba0..70d5411 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/mixins/system/hooks/HasInteractionId_see-also.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/mixins/system/hooks/HasInteractionId_see-also.adoc
@@ -8,7 +8,7 @@
Some of the extension/mapping modules that have entities that implement this mixee are:
* xref:security:audit-trail:about.adoc[Auditer] module: `AuditEntry` entity
-* xref:userguide:command-log:about.adoc[Command Log] module: `PublishedCommandForJdo` entity
+* xref:userguide:command-log:about.adoc[Command Log] module: `PublishedCommand` entity
* xref:mappings:outbox-publisher:about.adoc[Outbox Publisher] module: `OutboxEvent` entity
diff --git a/antora/components/refguide/modules/applib-classes/pages/roles-mixins-contributees/contributee.adoc b/antora/components/refguide/modules/applib-classes/pages/roles-mixins-contributees/contributee.adoc
index 763c42e..4c70c38 100644
--- a/antora/components/refguide/modules/applib-classes/pages/roles-mixins-contributees/contributee.adoc
+++ b/antora/components/refguide/modules/applib-classes/pages/roles-mixins-contributees/contributee.adoc
@@ -36,7 +36,7 @@ Some of the extension/mapping modules that have domain entity/ies that implement
* xref:security:ROOT:about.adoc[SecMan extension]: `ApplicationUser` entity
* xref:security:audit-trail:about.adoc[Auditer] module: `AuditEntry` entity
-* xref:userguide:command-log:about.adoc[Command Log] module: `PublishedCommandForJdo` entity
+* xref:userguide:command-log:about.adoc[Command Log] module: `PublishedCommand` entity
* xref:mappings:outbox-publisher:about.adoc[Outbox Publisher] module: `OutboxEvent` entity
* xref:security:session-log:about.adoc[Session Log] module: `SessionLogEntry` entity
* xref:subdomains:settings:about.adoc[Settings] module: `UserSettingJdo` entity
diff --git a/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java
index fc2a2f3..1b3eba3 100644
--- a/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java
+++ b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java
@@ -22,7 +22,9 @@ package org.apache.isis.extensions.commandlog.applib;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
+import org.apache.isis.extensions.commandlog.applib.app.CommandServiceMenu;
import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand;
+import org.apache.isis.extensions.commandlog.applib.subscriptions.PublishedCommandSubscriber;
import org.apache.isis.testing.fixtures.applib.IsisModuleTestingFixturesApplib;
/**
@@ -33,8 +35,9 @@ import org.apache.isis.testing.fixtures.applib.IsisModuleTestingFixturesApplib;
// modules
IsisModuleTestingFixturesApplib.class,
-
// @Services
+ CommandServiceMenu.class,
+ PublishedCommandSubscriber.class,
PublishedCommand.TitleProvider.class,
PublishedCommand.TableColumnOrderDefault.class,
diff --git a/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandServiceMenu.java b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandServiceMenu.java
new file mode 100644
index 0000000..dbbf7e4
--- /dev/null
+++ b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandServiceMenu.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.extensions.commandlog.applib.app;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.BookmarkPolicy;
+import org.apache.isis.applib.annotation.Domain;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.DomainServiceLayout;
+import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Optionality;
+import org.apache.isis.applib.annotation.Parameter;
+import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.annotation.RestrictTo;
+import org.apache.isis.applib.annotation.SemanticsOf;
+import org.apache.isis.applib.services.clock.ClockService;
+import org.apache.isis.extensions.commandlog.applib.IsisModuleExtCommandLogApplib;
+import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand;
+import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommandRepository;
+
+import lombok.RequiredArgsConstructor;
+
+/**
+ * @since 2.0 {@index}
+ */
+@DomainService(
+ nature = NatureOfService.VIEW,
+ logicalTypeName = CommandServiceMenu.LOGICAL_TYPE_NAME
+)
+@DomainServiceLayout(
+ named = "Activity",
+ menuBar = DomainServiceLayout.MenuBar.SECONDARY
+)
+@Named(CommandServiceMenu.LOGICAL_TYPE_NAME)
+@javax.annotation.Priority(PriorityPrecedence.MIDPOINT)
+@RequiredArgsConstructor
+public class CommandServiceMenu {
+
+ public final static String LOGICAL_TYPE_NAME = IsisModuleExtCommandLogApplib.NAMESPACE + ".CommandServiceMenu";
+
+ public static abstract class ActionDomainEvent<T> extends IsisModuleExtCommandLogApplib.ActionDomainEvent<T> { }
+
+ final ClockService clockService;
+ final PublishedCommandRepository publishedCommandRepository;
+
+
+ @Action(domainEvent = activeCommands.DomainEvent.class, semantics = SemanticsOf.SAFE)
+ @ActionLayout(bookmarking = BookmarkPolicy.AS_ROOT, cssClassFa = "fa-bolt", sequence="10")
+ public class activeCommands {
+ public class DomainEvent extends ActionDomainEvent<CommandServiceMenu.activeCommands> { }
+
+ @MemberSupport public List<PublishedCommand> act() {
+ return publishedCommandRepository.findCurrent();
+ }
+ @MemberSupport public boolean hideAct() {
+ return publishedCommandRepository == null;
+ }
+ }
+
+
+ @Action(domainEvent = findCommands.DomainEvent.class, semantics = SemanticsOf.SAFE)
+ @ActionLayout(cssClassFa = "fa-search", sequence="20")
+ public class findCommands {
+ public class DomainEvent extends ActionDomainEvent<CommandServiceMenu.findCommands> { }
+
+ @MemberSupport public List<PublishedCommand> act(
+ final @Nullable LocalDate from,
+ final @Nullable LocalDate to) {
+ return publishedCommandRepository.findByFromAndTo(from, to);
+ }
+ @MemberSupport public boolean hideAct() {
+ return publishedCommandRepository == null;
+ }
+ @MemberSupport public LocalDate default0Act() {
+ return now().minusDays(7);
+ }
+ @MemberSupport public LocalDate default1Act() {
+ return now();
+ }
+ }
+
+
+ @Action(domainEvent = findCommandById.DomainEvent.class, semantics = SemanticsOf.SAFE)
+ @ActionLayout(cssClassFa = "fa-crosshairs", sequence="30")
+ public class findCommandById {
+ public class DomainEvent extends ActionDomainEvent<CommandServiceMenu.findCommandById> { }
+
+ @MemberSupport public PublishedCommand act(
+ final UUID transactionId) {
+ return publishedCommandRepository.findByInteractionId(transactionId).orElse(null);
+ }
+ @MemberSupport public boolean hideAct() {
+ return publishedCommandRepository == null;
+ }
+ }
+
+
+ @Action(domainEvent = truncateLog.DomainEvent.class, semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE, restrictTo = RestrictTo.PROTOTYPING)
+ @ActionLayout(cssClassFa = "fa-trash", sequence="40")
+ public class truncateLog {
+ public class DomainEvent extends ActionDomainEvent<CommandServiceMenu.truncateLog> { }
+
+ @MemberSupport public void act() {
+ publishedCommandRepository.truncateLog();
+ }
+ }
+
+ private LocalDate now() {
+ return clockService.getClock().nowAsLocalDate(ZoneId.systemDefault());
+ }
+}
+
diff --git a/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/PublishedCommandRepositoryAbstract.java b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/PublishedCommandRepositoryAbstract.java
index 2b329b4..ba19aa0 100644
--- a/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/PublishedCommandRepositoryAbstract.java
+++ b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/PublishedCommandRepositoryAbstract.java
@@ -43,6 +43,7 @@ import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.repository.RepositoryService;
import org.apache.isis.applib.util.schema.CommandDtoUtils;
import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.factory._InstanceUtil;
import org.apache.isis.schema.cmd.v2.CommandDto;
import org.apache.isis.schema.cmd.v2.CommandsDto;
import org.apache.isis.schema.cmd.v2.MapDto;
@@ -327,8 +328,6 @@ implements PublishedCommandRepository {
return publishedCommand;
}
- protected abstract PublishedCommand newPublishedCommand();
-
@Override
public void persist(final PublishedCommand publishedCommand) {
repositoryService().persist(publishedCommand);
@@ -339,6 +338,10 @@ implements PublishedCommandRepository {
repositoryService().removeAll(PublishedCommand.class);
}
+ public PublishedCommand newPublishedCommand() {
+ return _InstanceUtil.createInstance(publishedCommandClass, PublishedCommand.class);
+ }
+
private RepositoryService repositoryService() {
return repositoryServiceProvider.get();
}
diff --git a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/CommandSubscriberForJdo.java b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/subscriptions/PublishedCommandSubscriber.java
similarity index 53%
rename from extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/CommandSubscriberForJdo.java
rename to extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/subscriptions/PublishedCommandSubscriber.java
index 13a9e24..2d8a541 100644
--- a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/CommandSubscriberForJdo.java
+++ b/extensions/core/command-log/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/subscriptions/PublishedCommandSubscriber.java
@@ -16,9 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.extensions.commandlog.jdo;
+package org.apache.isis.extensions.commandlog.applib.subscriptions;
+
+import java.util.UUID;
-import javax.inject.Inject;
import javax.inject.Named;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -28,25 +29,24 @@ import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.publishing.spi.CommandSubscriber;
import org.apache.isis.applib.util.JaxbUtil;
-import org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdo;
-import org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdoRepository;
+import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommandRepositoryAbstract;
import lombok.RequiredArgsConstructor;
-import lombok.val;
import lombok.extern.log4j.Log4j2;
+import lombok.val;
/**
* @since 2.0 {@index}
*/
@Service
-@Named("isis.ext.commandLog.CommandSubscriberForJdo")
+@Named("isis.ext.commandLog.PublishedCommandSubscriber")
@javax.annotation.Priority(PriorityPrecedence.MIDPOINT) // after JdoPersistenceLifecycleService
-@Qualifier("Jdo")
+@Qualifier("Default")
@Log4j2
@RequiredArgsConstructor
-public class CommandSubscriberForJdo implements CommandSubscriber {
+public class PublishedCommandSubscriber implements CommandSubscriber {
- @Inject final PublishedCommandForJdoRepository commandJdoRepository;
+ final PublishedCommandRepositoryAbstract<?> publishedCommandRepository;
@Override
public void onCompleted(Command command) {
@@ -55,33 +55,38 @@ public class CommandSubscriberForJdo implements CommandSubscriber {
return;
}
- val existingCommandJdoIfAny =
- commandJdoRepository.findByInteractionId(command.getInteractionId());
- if(existingCommandJdoIfAny.isPresent()) {
+ var commandInteractionId = command.getInteractionId();
+ final var existingCommandIfAny =
+ publishedCommandRepository.findByInteractionId(commandInteractionId);
+
+ if(existingCommandIfAny.isPresent()) {
+ // this isn't expected to happen; we just log the fact if it does
+ log.warn("Unexpectedly found existing command with interactionId '{}'; ignoring", commandInteractionId);
+
if(log.isDebugEnabled()) {
- // this isn't expected to happen ... we just log the fact if it does
- val existingCommandDto = existingCommandJdoIfAny.get().getCommandDto();
- val existingCommandDtoXml = JaxbUtil.toXml(existingCommandDto).presentElse("Dto to Xml failure");
- val commandDtoXml = JaxbUtil.toXml(command.getCommandDto()).presentElse("Dto to Xml failure");
+ val existingCommandDto = existingCommandIfAny.get().getCommandDto();
+
+ val existingCommandDtoXml = JaxbUtil.toXml(existingCommandDto).presentElse("Could not extract XML for existing command");
+ val commandDtoXml = JaxbUtil.toXml(command.getCommandDto()).presentElse("Could not extract XML for received command");
log.debug("existing: \n{}", existingCommandDtoXml);
- log.debug("proposed: \n{}", commandDtoXml);
+ log.debug("received: \n{}", commandDtoXml);
}
- } else {
- val commandJdo = new PublishedCommandForJdo(command);
- val parent = command.getParent();
- val parentJdo =
- parent != null
- ? commandJdoRepository
- .findByInteractionId(parent.getInteractionId())
- .orElse(null)
- : null;
- commandJdo.setParent(parentJdo);
- commandJdoRepository.persist(commandJdo);
+ return;
}
-
+ val publishedCommand = publishedCommandRepository.newPublishedCommand();
+ val parent = command.getParent();
+ val parentCommand =
+ parent != null
+ ? publishedCommandRepository
+ .findByInteractionId(parent.getInteractionId())
+ .orElse(null)
+ : null;
+ publishedCommand.setParent(parentCommand);
+ publishedCommandRepository.persist(publishedCommand);
}
+
}
diff --git a/extensions/core/command-log/jdo/src/main/java/META-INF/persistence.xml b/extensions/core/command-log/jdo/src/main/java/META-INF/persistence.xml
index 9a6b5df..974fec7 100644
--- a/extensions/core/command-log/jdo/src/main/java/META-INF/persistence.xml
+++ b/extensions/core/command-log/jdo/src/main/java/META-INF/persistence.xml
@@ -14,6 +14,6 @@
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="org-apache-isis-extensions-commandlog">
- <class>org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdo</class>
+ <class>org.apache.isis.extensions.commandlog.jdo.dom.PublishedCommand</class>
</persistence-unit>
</persistence>
diff --git a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
index 2a06374..0d71b9a 100644
--- a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
+++ b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
@@ -22,11 +22,11 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdo;
-import org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdoRepository;
-import org.apache.isis.extensions.commandlog.jdo.ui.CommandServiceMenu;
import org.apache.isis.extensions.commandlog.applib.IsisModuleExtCommandLogApplib;
+import org.apache.isis.extensions.commandlog.jdo.dom.PublishedCommand;
+import org.apache.isis.extensions.commandlog.jdo.dom.PublishedCommandRepository;
import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
+import org.apache.isis.testing.fixtures.applib.modules.ModuleWithFixtures;
import org.apache.isis.testing.fixtures.applib.teardown.jdo.TeardownFixtureJdoAbstract;
/**
@@ -34,34 +34,34 @@ import org.apache.isis.testing.fixtures.applib.teardown.jdo.TeardownFixtureJdoAb
*/
@Configuration
@Import({
- // @DomainService's
- PublishedCommandForJdoRepository.class
- , CommandServiceMenu.class
+ // module dependencies
+ IsisModuleExtCommandLogApplib.class
- // @Service's
- , PublishedCommandForJdo.TableColumnOrderDefault.class
+ // @DomainService's
+ , PublishedCommandRepository.class
// entities
- , PublishedCommandForJdo.class
+ , PublishedCommand.class
})
@ComponentScan(
basePackageClasses= {
IsisModuleExtCommandLogJdo.class
})
-public class IsisModuleExtCommandLogJdo
-implements IsisModuleExtCommandLogApplib {
-
- public static final String NAMESPACE = "isis.ext.commandLog";
+public class IsisModuleExtCommandLogJdo {
/**
* For tests that need to delete the command table first.
- * Should be run in the @Before of the test.
+ * Should be run in the <code>@Before</code> of the test.
+ *
+ * <p>
+ * NOTE: this class deliberately does <i>not</i> implement {@link ModuleWithFixtures}.
+ * </p>
*/
- public FixtureScript getTeardownFixtureWillDelete() {
+ public FixtureScript getTeardownFixture() {
return new TeardownFixtureJdoAbstract() {
@Override
protected void execute(final ExecutionContext executionContext) {
- deleteFrom(PublishedCommandForJdo.class);
+ deleteFrom(PublishedCommand.class);
}
};
}
diff --git a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdo.java b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/PublishedCommand.java
similarity index 66%
rename from extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdo.java
rename to extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/PublishedCommand.java
index b0d2679..13982e5 100644
--- a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdo.java
+++ b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/PublishedCommand.java
@@ -16,20 +16,31 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.extensions.commandlog.jdo.entities;
+package org.apache.isis.extensions.commandlog.jdo.dom;
import java.sql.Timestamp;
import java.util.UUID;
+import javax.jdo.annotations.DatastoreIdentity;
+import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
+import javax.jdo.annotations.Index;
+import javax.jdo.annotations.Indices;
+import javax.jdo.annotations.Inheritance;
+import javax.jdo.annotations.InheritanceStrategy;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Queries;
+import javax.jdo.annotations.Query;
+import javax.jdo.annotations.Unique;
+import javax.jdo.annotations.Uniques;
import org.apache.isis.applib.annotation.DomainObject;
import org.apache.isis.applib.annotation.DomainObjectLayout;
+import org.apache.isis.applib.annotation.Editing;
import org.apache.isis.applib.mixins.system.DomainChangeRecord;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.types.MemberIdentifierType;
import org.apache.isis.commons.internal.base._Casts;
-import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand;
import org.apache.isis.extensions.commandlog.applib.dom.ReplayState;
import org.apache.isis.schema.cmd.v2.CommandDto;
@@ -38,162 +49,176 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
-@javax.jdo.annotations.PersistenceCapable(
+@PersistenceCapable(
identityType=IdentityType.APPLICATION,
schema = "isisExtensionsCommandLog",
- table = "PublishedCommand")
-
+ table = "PublishedCommand"
+)
+@Uniques({
+ @Unique(
+ name = "PublishedCommand__interactionId__UNQ",
+ members = {
+ "interactionId"
+ })
+})
+@Indices({
+ @Index(
+ name = "PublishedCommand__startedAt__timestamp__IDX",
+ members = {"startedAt", "timestamp"}),
+ @Index(
+ name = "PublishedCommand__timestamp__IDX",
+ members = {"timestamp"}
+ ),
+})
+@Inheritance(
+ strategy = InheritanceStrategy.NEW_TABLE)
+@DatastoreIdentity(
+ strategy = IdGeneratorStrategy.NATIVE, column = "id")
// queries that use RANGE 0,2 should instead be RANGE 0,1, however this results in DataNucleus submitting "FETCH NEXT ROW ONLY"
// which SQL Server doesn't understand. However, as workaround, SQL Server *does* understand FETCH NEXT 2 ROWS ONLY
-@javax.jdo.annotations.Queries( {
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_INTERACTION_ID,
+@Queries( {
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_INTERACTION_ID,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE interactionId == :interactionId "),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_PARENT,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_PARENT,
value="SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE parent == :parent "),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_CURRENT,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_CURRENT,
value="SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE completedAt == null "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_COMPLETED,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_COMPLETED,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE completedAt != null "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_RECENT_BY_TARGET,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_RECENT_BY_TARGET,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE target == :target "
+ "ORDER BY this.timestamp DESC "
+ "RANGE 0,30"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_BETWEEEN,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_BETWEEEN,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE target == :target "
+ "&& timestamp >= :from "
+ "&& timestamp <= :to "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_AFTER,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_AFTER,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE target == :target "
+ "&& timestamp >= :from "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_BEFORE,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_BEFORE,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE target == :target "
+ "&& timestamp <= :to "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TARGET,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE target == :target "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_BETWEEN,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_BETWEEN,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE timestamp >= :from "
+ "&& timestamp <= :to "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_AFTER,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_AFTER,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE timestamp >= :from "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_BEFORE,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_BEFORE,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE timestamp <= :to "
+ "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_RECENT_BY_USERNAME,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_RECENT_BY_USERNAME,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE username == :username "
+ "ORDER BY this.timestamp DESC "
+ "RANGE 0,30"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_FIRST,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_FIRST,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
- + " WHERE startedAt != null "
+ + "FROM " + PublishedCommand.FQCN
+ + " WHERE startedAt != null "
+ " && completedAt != null "
+ "ORDER BY this.timestamp ASC "
+ "RANGE 0,2"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_SINCE,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_SINCE,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE timestamp > :timestamp "
+ " && startedAt != null "
+ " && completedAt != null "
+ "ORDER BY this.timestamp ASC"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_MOST_RECENT_REPLAYED,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_MOST_RECENT_REPLAYED,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE (replayState == 'OK' || replayState == 'FAILED') "
+ "ORDER BY this.timestamp DESC "
+ "RANGE 0,2"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_MOST_RECENT_COMPLETED,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_MOST_RECENT_COMPLETED,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE startedAt != null "
+ " && completedAt != null "
+ "ORDER BY this.timestamp DESC "
+ "RANGE 0,2"),
- @javax.jdo.annotations.Query(
- name = PublishedCommand.NAMED_QUERY_FIND_NOT_YET_REPLAYED,
+ @Query(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_NOT_YET_REPLAYED,
value = "SELECT "
- + "FROM " + PublishedCommandForJdo.FQCN
+ + "FROM " + PublishedCommand.FQCN
+ " WHERE replayState == 'PENDING' "
+ "ORDER BY this.timestamp ASC "
+ "RANGE 0,10"), // same as batch size
})
-@javax.jdo.annotations.Indices({
- @javax.jdo.annotations.Index(name = "CommandJdo__startedAt__timestamp__IDX", members = { "startedAt", "timestamp" }),
- @javax.jdo.annotations.Index(name = "CommandJdo__timestamp__IDX", members = { "timestamp" }),
-})
@DomainObject(
- logicalTypeName = PublishedCommand.LOGICAL_TYPE_NAME
-)
-@DomainObjectLayout(
- named = "Published Command"
+ logicalTypeName = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.LOGICAL_TYPE_NAME,
+ editing = Editing.DISABLED
)
@NoArgsConstructor(access = AccessLevel.PACKAGE)
-public class PublishedCommandForJdo extends PublishedCommand {
+public class PublishedCommand extends org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand {
- protected final static String FQCN = "org.apache.isis.extensions.commandlog.jdo.entities.CommandJdo";
+ protected final static String FQCN = "org.apache.isis.extensions.commandlog.jdo.dom.PublishedCommand";
// EVENTS
// (see superclass)
// CONSTRUCTORS
- public PublishedCommandForJdo(
+ public PublishedCommand(
final CommandDto commandDto,
final ReplayState replayState,
final int targetIndex) {
@@ -294,15 +319,15 @@ public class PublishedCommandForJdo extends PublishedCommand {
@javax.jdo.annotations.Persistent
@javax.jdo.annotations.Column(name="parentId", allowsNull="true")
- private PublishedCommandForJdo parent;
+ private PublishedCommand parent;
@Parent
@Override
- public PublishedCommand getParent() {
+ public org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand getParent() {
return parent;
}
@Override
- public void setParent(PublishedCommand parent) {
+ public void setParent(org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand parent) {
this.parent = _Casts.uncheckedCast(parent);
}
@@ -338,7 +363,6 @@ public class PublishedCommandForJdo extends PublishedCommand {
// LOGICAL MEMBER IDENTIFIER
@javax.jdo.annotations.Column(allowsNull="false", length = MemberIdentifierType.Meta.MAX_LEN)
- @Getter @Setter
private String logicalMemberIdentifier;
@LogicalMemberIdentifier
diff --git a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdoRepository.java b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/PublishedCommandRepository.java
similarity index 63%
copy from extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdoRepository.java
copy to extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/PublishedCommandRepository.java
index 7f38ebc..12c0043 100644
--- a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdoRepository.java
+++ b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/PublishedCommandRepository.java
@@ -16,37 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.extensions.commandlog.jdo.entities;
+package org.apache.isis.extensions.commandlog.jdo.dom;
-import javax.inject.Inject;
import javax.inject.Named;
-import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
-import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand;
+import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommandRepositoryAbstract;
-import org.apache.isis.persistence.jdo.applib.services.JdoSupportService;
-import lombok.RequiredArgsConstructor;
-
-/**
- * Provides supporting functionality for querying and persisting
- * {@link PublishedCommandForJdo command} entities.
- */
@Service
@Named("isis.ext.commandLog.PublishedCommandRepository")
@javax.annotation.Priority(PriorityPrecedence.MIDPOINT)
@Qualifier("Jdo")
-public class PublishedCommandForJdoRepository
-extends PublishedCommandRepositoryAbstract<PublishedCommandForJdo> {
+public class PublishedCommandRepository
+extends PublishedCommandRepositoryAbstract<PublishedCommand> {
- public PublishedCommandForJdoRepository() {
- super(PublishedCommandForJdo.class);
+ public PublishedCommandRepository() {
+ super(PublishedCommand.class);
}
- @Override protected PublishedCommand newPublishedCommand() {
- return new PublishedCommandForJdo();
+ @Override public PublishedCommand newPublishedCommand() {
+ return new PublishedCommand();
}
}
diff --git a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/ui/CommandServiceMenu.java b/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/ui/CommandServiceMenu.java
deleted file mode 100644
index e50a186..0000000
--- a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/ui/CommandServiceMenu.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.extensions.commandlog.jdo.ui;
-
-import java.time.LocalDate;
-import java.time.ZoneId;
-import java.util.List;
-import java.util.UUID;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.applib.annotation.BookmarkPolicy;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.applib.annotation.MemberSupport;
-import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.Optionality;
-import org.apache.isis.applib.annotation.Parameter;
-import org.apache.isis.applib.annotation.ParameterLayout;
-import org.apache.isis.applib.annotation.PriorityPrecedence;
-import org.apache.isis.applib.annotation.RestrictTo;
-import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.applib.services.clock.ClockService;
-import org.apache.isis.extensions.commandlog.jdo.IsisModuleExtCommandLogJdo;
-import org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdo;
-import org.apache.isis.extensions.commandlog.jdo.entities.PublishedCommandForJdoRepository;
-
-import lombok.RequiredArgsConstructor;
-
-/**
- * @since 2.0 {@index}
- */
-@DomainService(
- nature = NatureOfService.VIEW,
- logicalTypeName = CommandServiceMenu.LOGICAL_TYPE_NAME
-)
-@DomainServiceLayout(
- named = "Activity",
- menuBar = DomainServiceLayout.MenuBar.SECONDARY
-)
-@Named(CommandServiceMenu.LOGICAL_TYPE_NAME)
-@javax.annotation.Priority(PriorityPrecedence.EARLY)
-@Qualifier("Jdo")
-@RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class CommandServiceMenu {
-
- public final static String LOGICAL_TYPE_NAME = IsisModuleExtCommandLogJdo.NAMESPACE + ".CommandServiceMenu";
-
- public static abstract class PropertyDomainEvent<T>
- extends IsisModuleExtCommandLogJdo.PropertyDomainEvent<CommandServiceMenu, T> { }
- public static abstract class CollectionDomainEvent<T>
- extends IsisModuleExtCommandLogJdo.CollectionDomainEvent<CommandServiceMenu, T> { }
- public static abstract class ActionDomainEvent
- extends IsisModuleExtCommandLogJdo.ActionDomainEvent<CommandServiceMenu> {
- }
-
- final PublishedCommandForJdoRepository commandServiceRepository;
- final ClockService clockService;
-
- public static class ActiveCommandsDomainEvent extends ActionDomainEvent { }
- @Action(domainEvent = ActiveCommandsDomainEvent.class, semantics = SemanticsOf.SAFE)
- @ActionLayout(bookmarking = BookmarkPolicy.AS_ROOT, cssClassFa = "fa-bolt", sequence="10")
- public List<PublishedCommandForJdo> activeCommands() {
- return commandServiceRepository.findCurrent();
- }
- @MemberSupport public boolean hideActiveCommands() {
- return commandServiceRepository == null;
- }
-
-
- public static class FindCommandsDomainEvent extends ActionDomainEvent { }
- @Action(domainEvent = FindCommandsDomainEvent.class, semantics = SemanticsOf.SAFE)
- @ActionLayout(cssClassFa = "fa-search", sequence="20")
- public List<PublishedCommandForJdo> findCommands(
- @Parameter(optionality= Optionality.OPTIONAL)
- @ParameterLayout(named="From")
- final LocalDate from,
- @Parameter(optionality= Optionality.OPTIONAL)
- @ParameterLayout(named="To")
- final LocalDate to) {
- return commandServiceRepository.findByFromAndTo(from, to);
- }
- @MemberSupport public boolean hideFindCommands() {
- return commandServiceRepository == null;
- }
- @MemberSupport public LocalDate default0FindCommands() {
- return now().minusDays(7);
- }
- @MemberSupport public LocalDate default1FindCommands() {
- return now();
- }
-
-
- public static class FindCommandByIdDomainEvent extends ActionDomainEvent { }
- @Action(domainEvent = FindCommandByIdDomainEvent.class, semantics = SemanticsOf.SAFE)
- @ActionLayout(cssClassFa = "fa-crosshairs", sequence="30")
- public PublishedCommandForJdo findCommandById(
- @ParameterLayout(named="Transaction Id")
- final UUID transactionId) {
- return commandServiceRepository.findByInteractionId(transactionId).orElse(null);
- }
- @MemberSupport public boolean hideFindCommandById() {
- return commandServiceRepository == null;
- }
-
-
- public static class TruncateLogDomainEvent extends ActionDomainEvent { }
- @Action(domainEvent = TruncateLogDomainEvent.class, semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE, restrictTo = RestrictTo.PROTOTYPING)
- @ActionLayout(cssClassFa = "fa-trash", sequence="40")
- public void truncateLog() {
- commandServiceRepository.truncateLog();
- }
-
-
- private LocalDate now() {
- return clockService.getClock().nowAsLocalDate(ZoneId.systemDefault());
- }
-
-}
-
diff --git a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java
index 41a55ac..ac8b754 100644
--- a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java
+++ b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java
@@ -22,23 +22,26 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.apache.isis.extensions.commandlog.jpa.entities.CommandJpa;
-import org.apache.isis.extensions.commandlog.jpa.entities.CommandJpaRepository;
+import org.apache.isis.extensions.commandlog.applib.IsisModuleExtCommandLogApplib;
+import org.apache.isis.extensions.commandlog.jpa.dom.PublishedCommand;
+import org.apache.isis.extensions.commandlog.jpa.dom.PublishedCommandRepository;
+import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
+import org.apache.isis.testing.fixtures.applib.modules.ModuleWithFixtures;
+import org.apache.isis.testing.fixtures.applib.teardown.jdo.TeardownFixtureJdoAbstract;
/**
* @since 2.0 {@index}
*/
@Configuration
@Import({
- // @DomainService's
- CommandJpaRepository.class
-//TODO , CommandServiceMenu.class
+ // module dependencies
+ IsisModuleExtCommandLogApplib.class
- // @Service's
- , CommandJpa.TableColumnOrderDefault.class
+ // @DomainService's
+ , PublishedCommandRepository.class
// entities
- , CommandJpa.class
+ , PublishedCommand.class
})
@ComponentScan(
basePackageClasses= {
@@ -46,6 +49,21 @@ import org.apache.isis.extensions.commandlog.jpa.entities.CommandJpaRepository;
})
public class IsisModuleExtCommandLogJpa {
- public static final String NAMESPACE = "isis.ext.commandLog";
+ /**
+ * For tests that need to delete the command table first.
+ * Should be run in the <code>@Before</code> of the test.
+ *
+ * <p>
+ * NOTE: this class deliberately does <i>not</i> implement {@link ModuleWithFixtures}.
+ * </p>
+ */
+ public FixtureScript getTeardownFixture() {
+ return new TeardownFixtureJdoAbstract() {
+ @Override
+ protected void execute(final ExecutionContext executionContext) {
+ deleteFrom(PublishedCommand.class);
+ }
+ };
+ }
}
diff --git a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/PublishedCommand.java b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/PublishedCommand.java
new file mode 100644
index 0000000..53967a4
--- /dev/null
+++ b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/PublishedCommand.java
@@ -0,0 +1,504 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.extensions.commandlog.jpa.dom;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.Index;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Service;
+
+import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.annotation.Editing;
+import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.Property;
+import org.apache.isis.applib.annotation.PropertyLayout;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.mixins.system.DomainChangeRecord;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.command.CommandOutcomeHandler;
+import org.apache.isis.applib.services.tablecol.TableColumnOrderForCollectionTypeAbstract;
+import org.apache.isis.applib.types.MemberIdentifierType;
+import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.extensions.commandlog.applib.dom.ReplayState;
+import org.apache.isis.extensions.commandlog.applib.util.BigDecimalUtils;
+import org.apache.isis.extensions.commandlog.applib.util.StringUtils;
+import org.apache.isis.persistence.jpa.applib.integration.IsisEntityListener;
+import org.apache.isis.schema.cmd.v2.CommandDto;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.val;
+
+@Entity
+@Table(
+ schema = "isisExtensionsCommandLog",
+ name = "PublishedCommand",
+ uniqueConstraints =
+ @UniqueConstraint(
+ name = "PublishedCommand__interactionId__UNQ",
+ columnNames = {
+ "interactionId"
+ }),
+ indexes = {
+ @Index(
+ name = "PublishedCommand__startedAt__timestamp__IDX",
+ columnList = "startedAt, timestamp"
+ ),
+ @Index(
+ name = "PublishedCommand__timestamp__IDX",
+ columnList = "timestamp"
+ )
+ }
+)
+@NamedQueries({
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_INTERACTION_ID,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.interactionId = :interactionId"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_PARENT,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.parent = :parent "),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_CURRENT,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.completedAt is null "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_COMPLETED,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.completedAt is not null "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_RECENT_BY_TARGET,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.target = :target "
+ + "ORDER BY pc.timestamp DESC "),
+ // TODO: query.setMaxResults(30)
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_BETWEEEN,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.target = :target "
+ + " AND pc.timestamp >= :from "
+ + " AND pc.timestamp <= :to "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_AFTER,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.target = :target "
+ + " AND pc.timestamp >= :from "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET_AND_TIMESTAMP_BEFORE,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.target = :target "
+ + " AND pc.timestamp <= :to "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TARGET,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.target = :target "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_BETWEEN,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.timestamp >= :from "
+ + " AND pc.timestamp <= :to "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_AFTER,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.timestamp >= :from "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_BY_TIMESTAMP_BEFORE,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.timestamp <= :to "
+ + "ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " ORDER BY pc.timestamp DESC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_RECENT_BY_USERNAME,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.username = :username "
+ + "ORDER BY pc.timestamp DESC "),
+ // TODO: query.setMaxResults(30)
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_FIRST,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.startedAt is not null "
+ + " and pc.completedAt is not null "
+ + "ORDER BY pc.timestamp ASC "),
+ // TODO: query.setMaxResults(2)
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_SINCE,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.timestamp > :timestamp "
+ + " AND pc.startedAt is not null "
+ + " AND pc.completedAt is not null "
+ + "ORDER BY pc.timestamp ASC"),
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_MOST_RECENT_REPLAYED,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.replayState = 'OK' OR pc.replayState = 'FAILED' "
+ + "ORDER BY pc.timestamp DESC "),
+ // TODO: query.setMaxResults(2)
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_MOST_RECENT_COMPLETED,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.startedAt is not null "
+ + " AND pc.completedAt is not null "
+ + "ORDER BY pc.timestamp DESC "),
+ // TODO: query.setMaxResults(2)
+ @NamedQuery(
+ name = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.NAMED_QUERY_FIND_NOT_YET_REPLAYED,
+ query = "SELECT pc "
+ + "FROM PublishedCommand pc"
+ + " WHERE pc.replayState = 'PENDING' "
+ + "ORDER BY pc.timestamp ASC "),
+ // TODO: query.setMaxResults(2) // same as batch size
+})
+@EntityListeners(IsisEntityListener.class)
+@DomainObject(
+ logicalTypeName = org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand.LOGICAL_TYPE_NAME,
+ editing = Editing.DISABLED
+)
+@NoArgsConstructor
+public class PublishedCommand extends org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand {
+
+ protected final static String FQCN = "org.apache.isis.extensions.commandlog.jpa.dom.PublishedCommand";
+
+ // EVENTS
+ // (see superclass)
+
+ // CONSTRUCTORS
+
+ public PublishedCommand(
+ final CommandDto commandDto,
+ final ReplayState replayState,
+ final int targetIndex) {
+
+ super(commandDto, replayState, targetIndex);
+ }
+
+
+ // TITLE
+ // (see superclass)
+
+
+ // (CHANGE) TYPE
+ // (derived - see superclass)
+
+
+ // INTERACTION ID
+
+ // TODO
+ private UUID interactionId;
+
+ @DomainChangeRecord.InteractionId
+ @Override
+ public UUID getInteractionId() {
+ return interactionId;
+ }
+ @Override
+ public void setInteractionId(UUID interactionId) {
+ this.interactionId = interactionId;
+ }
+
+
+ // USER NAME
+
+ // TODO
+ private String username;
+
+ @DomainChangeRecord.Username
+ @Override
+ public String getUsername() { return username; }
+ @Override
+ public void setUsername(String username) { this.username = username; }
+
+
+ // TIMESTAMP
+
+ // TODO
+ private Timestamp timestamp;
+
+ @DomainChangeRecord.TimestampMeta
+ @Override
+ public Timestamp getTimestamp() {
+ return timestamp;
+ }
+ @Override
+ public void setTimestamp(Timestamp timestamp) {
+ this.timestamp = timestamp;
+ }
+
+
+
+ // REPLAY STATE
+
+ // TODO
+ private ReplayState replayState;
+
+ @ReplayStateMeta
+ @Override
+ public ReplayState getReplayState() {
+ return replayState;
+ }
+ @Override
+ public void setReplayState(ReplayState replayState) {
+ this.replayState = replayState;
+ }
+
+
+ // REPLAY STATE FAILURE REASON
+
+ // TODO
+ private String replayStateFailureReason;
+
+ @ReplayStateFailureReason
+ @Override
+ public String getReplayStateFailureReason() {
+ return replayStateFailureReason;
+ }
+ @Override
+ public void setReplayStateFailureReason(String replayStateFailureReason) {
+ this.replayStateFailureReason = replayStateFailureReason;
+ }
+
+
+ // PARENT
+
+ // TODO
+ private PublishedCommand parent;
+
+ @Parent
+ @Override
+ public org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand getParent() {
+ return parent;
+ }
+ @Override
+ public void setParent(org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand parent) {
+ this.parent = _Casts.uncheckedCast(parent);
+ }
+
+
+
+ // TARGET
+
+ // TODO
+ private Bookmark target;
+
+ @DomainChangeRecord.TargetMeta
+ @Override
+ public Bookmark getTarget() {
+ return target;
+ }
+ @Override
+ public void setTarget(Bookmark target) {
+ this.target = target;
+ }
+
+
+ // TARGET MEMBER
+ // (derived - see superclass)
+
+
+
+ // LOCAL MEMBER
+ // (derived - see superclass)
+
+
+
+ // LOGICAL MEMBER IDENTIFIER
+
+ // TODO
+ private String logicalMemberIdentifier;
+
+ @LogicalMemberIdentifier
+ @Override
+ public String getLogicalMemberIdentifier() {
+ return logicalMemberIdentifier;
+ }
+ @Override
+ public void setLogicalMemberIdentifier(String logicalMemberIdentifier) {
+ this.logicalMemberIdentifier = logicalMemberIdentifier;
+ }
+
+
+ // COMMAND DTO
+
+ // TODO
+ private CommandDto commandDto;
+
+ @CommandDtoMeta
+ @Override
+ public CommandDto getCommandDto() {
+ return commandDto;
+ }
+ @Override
+ public void setCommandDto(CommandDto commandDto) {
+ this.commandDto = commandDto;
+ }
+
+
+ // STARTED AT
+
+ // TODO
+ private Timestamp startedAt;
+
+ @StartedAt
+ @Override
+ public Timestamp getStartedAt() {
+ return startedAt;
+ }
+ @Override
+ public void setStartedAt(Timestamp startedAt) {
+ this.startedAt = startedAt;
+ }
+
+
+ // COMPLETED AT
+
+ // TODO
+ private Timestamp completedAt;
+
+ @CompletedAt
+ @Override
+ public Timestamp getCompletedAt() {
+ return completedAt;
+ }
+ @Override
+ public void setCompletedAt(Timestamp completedAt) {
+ this.completedAt = completedAt;
+ }
+
+
+
+ // DURATION
+ // (derived - see superclass)
+
+
+
+ // COMPLETE
+ // (derived - see superclass)
+
+
+
+ // RESULT SUMMARY
+ // (derived - see superclass)
+
+
+
+ // RESULT
+
+ // TODO
+ private Bookmark result;
+
+ @Result
+ @Override
+ public Bookmark getResult() {
+ return result;
+ }
+ @Override
+ public void setResult(Bookmark result) {
+ this.result = result;
+ }
+
+
+ // EXCEPTION
+
+ // TODO
+ private String exception;
+
+ @ExceptionMeta
+ @Override
+ public String getException() {
+ return exception;
+ }
+ @Override
+ public void setException(final String exception) {
+ this.exception = exception;
+ }
+
+
+ // CAUSED EXCEPTION
+ // (derived - see superclass)
+
+
+
+ // PRE VALUE
+ // (derived - see superclass)
+
+
+
+ // POST VALUE
+ // (derived - see superclass)
+
+
+
+ // PROGRAMMATIC
+ // (see superclass)
+
+
+ // TO STRING etc
+ // (see superclass)
+
+
+}
+
diff --git a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdoRepository.java b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/PublishedCommandRepository.java
similarity index 63%
rename from extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdoRepository.java
rename to extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/PublishedCommandRepository.java
index 7f38ebc..d95ac4b 100644
--- a/extensions/core/command-log/jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/entities/PublishedCommandForJdoRepository.java
+++ b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/PublishedCommandRepository.java
@@ -16,37 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.extensions.commandlog.jdo.entities;
+package org.apache.isis.extensions.commandlog.jpa.dom;
-import javax.inject.Inject;
import javax.inject.Named;
-import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
-import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand;
+import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommandRepositoryAbstract;
-import org.apache.isis.persistence.jdo.applib.services.JdoSupportService;
-import lombok.RequiredArgsConstructor;
-
-/**
- * Provides supporting functionality for querying and persisting
- * {@link PublishedCommandForJdo command} entities.
- */
@Service
@Named("isis.ext.commandLog.PublishedCommandRepository")
@javax.annotation.Priority(PriorityPrecedence.MIDPOINT)
-@Qualifier("Jdo")
-public class PublishedCommandForJdoRepository
-extends PublishedCommandRepositoryAbstract<PublishedCommandForJdo> {
+@Qualifier("Jpa")
+public class PublishedCommandRepository
+extends PublishedCommandRepositoryAbstract<PublishedCommand> {
- public PublishedCommandForJdoRepository() {
- super(PublishedCommandForJdo.class);
+ public PublishedCommandRepository() {
+ super(PublishedCommand.class);
}
- @Override protected PublishedCommand newPublishedCommand() {
- return new PublishedCommandForJdo();
+ @Override public PublishedCommand newPublishedCommand() {
+ return new PublishedCommand();
}
}
diff --git a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/entities/CommandJpa.java b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/entities/CommandJpa.java
deleted file mode 100644
index 27c19f8..0000000
--- a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/entities/CommandJpa.java
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.extensions.commandlog.jpa.entities;
-
-import java.math.BigDecimal;
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.function.Consumer;
-
-import javax.persistence.Entity;
-
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.annotation.DomainObject;
-import org.apache.isis.applib.annotation.Editing;
-import org.apache.isis.applib.annotation.MemberSupport;
-import org.apache.isis.applib.annotation.PriorityPrecedence;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.applib.annotation.PropertyLayout;
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.jaxb.JavaSqlXMLGregorianCalendarMarshalling;
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.CommandOutcomeHandler;
-import org.apache.isis.applib.services.commanddto.conmap.UserDataKeys;
-import org.apache.isis.applib.services.tablecol.TableColumnOrderForCollectionTypeAbstract;
-import org.apache.isis.applib.util.TitleBuffer;
-import org.apache.isis.commons.functional.Result;
-import org.apache.isis.commons.internal.base._Strings;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
-import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommand;
-import org.apache.isis.extensions.commandlog.jpa.IsisModuleExtCommandLogJpa;
-import org.apache.isis.extensions.commandlog.applib.dom.ReplayState;
-import org.apache.isis.extensions.commandlog.applib.util.BigDecimalUtils;
-import org.apache.isis.extensions.commandlog.applib.util.StringUtils;
-import org.apache.isis.schema.cmd.v2.CommandDto;
-import org.apache.isis.schema.cmd.v2.MapDto;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.val;
-
-/**
- * A persistent representation of a {@link Command}.
- *
- * <p>
- * Use cases requiring persistence including auditing, and for replay of
- * commands for regression testing purposes.
- * </p>
- *
- * Note that this class doesn't subclass from {@link Command} ({@link Command}
- * is not an interface).
- */
-/* TODO migrate to JPA
-@javax.jdo.annotations.PersistenceCapable(
- identityType=IdentityType.APPLICATION,
- schema = "isisExtensionsCommandLog",
- table = "Command")
-@javax.jdo.annotations.Queries( {
- @javax.jdo.annotations.Query(
- name="findByInteractionIdStr",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE interactionIdStr == :interactionIdStr "),
- @javax.jdo.annotations.Query(
- name="findByParent",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE parent == :parent "),
- @javax.jdo.annotations.Query(
- name="findCurrent",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE completedAt == null "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findCompleted",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE completedAt != null "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findRecentByTarget",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE target == :target "
- + "ORDER BY this.timestamp DESC "
- + "RANGE 0,30"),
- @javax.jdo.annotations.Query(
- name="findByTargetAndTimestampBetween",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE target == :target "
- + "&& timestamp >= :from "
- + "&& timestamp <= :to "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findByTargetAndTimestampAfter",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE target == :target "
- + "&& timestamp >= :from "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findByTargetAndTimestampBefore",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE target == :target "
- + "&& timestamp <= :to "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findByTarget",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE target == :target "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findByTimestampBetween",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE timestamp >= :from "
- + "&& timestamp <= :to "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findByTimestampAfter",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE timestamp >= :from "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findByTimestampBefore",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE timestamp <= :to "
- + "ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="find",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " ORDER BY this.timestamp DESC"),
- @javax.jdo.annotations.Query(
- name="findRecentByUsername",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE username == :username "
- + "ORDER BY this.timestamp DESC "
- + "RANGE 0,30"),
- @javax.jdo.annotations.Query(
- name="findFirst",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE startedAt != null "
- + " && completedAt != null "
- + "ORDER BY this.timestamp ASC "
- + "RANGE 0,2"),
- // this should be RANGE 0,1 but results in DataNucleus submitting "FETCH NEXT ROW ONLY"
- // which SQL Server doesn't understand. However, as workaround, SQL Server *does* understand FETCH NEXT 2 ROWS ONLY
- @javax.jdo.annotations.Query(
- name="findSince",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE timestamp > :timestamp "
- + " && startedAt != null "
- + " && completedAt != null "
- + "ORDER BY this.timestamp ASC"),
- // most recent (replayed) command previously replicated from primary to
- // secondary. This should always exist except for the very first times
- // (after restored the prod DB to secondary).
- @javax.jdo.annotations.Query(
- name="findMostRecentReplayed",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE (replayState == 'OK' || replayState == 'FAILED') "
- + "ORDER BY this.timestamp DESC "
- + "RANGE 0,2"), // this should be RANGE 0,1 but results in DataNucleus submitting "FETCH NEXT ROW ONLY"
- // which SQL Server doesn't understand. However, as workaround, SQL Server *does* understand FETCH NEXT 2 ROWS ONLY
- // the most recent completed command, as queried on the
- // secondary, corresponding to the last command run on primary before the
- // production database was restored to the secondary
- @javax.jdo.annotations.Query(
- name="findMostRecentCompleted",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE startedAt != null "
- + " && completedAt != null "
- + "ORDER BY this.timestamp DESC "
- + "RANGE 0,2"),
- // this should be RANGE 0,1 but results in DataNucleus submitting "FETCH NEXT ROW ONLY"
- // which SQL Server doesn't understand. However, as workaround, SQL Server *does* understand FETCH NEXT 2 ROWS ONLY
- @javax.jdo.annotations.Query(
- name="findNotYetReplayed",
- value="SELECT "
- + "FROM " + CommandJdo.FQCN
- + " WHERE replayState == 'PENDING' "
- + "ORDER BY this.timestamp ASC "
- + "RANGE 0,10"), // same as batch size
-})
-@javax.jdo.annotations.Indices({
- @javax.jdo.annotations.Index(name = "CommandJdo__startedAt__timestamp__IDX", members = { "startedAt", "timestamp" }),
- @javax.jdo.annotations.Index(name = "CommandJdo__timestamp__IDX", members = { "timestamp" }),
-})
-*/
-@Entity
-@DomainObject(
- logicalTypeName = CommandJpa.LOGICAL_TYPE_NAME,
- editing = Editing.DISABLED
-)
-//@Log4j2
-@NoArgsConstructor
-public class CommandJpa extends PublishedCommand {
-
- public final static String LOGICAL_TYPE_NAME = IsisModuleExtCommandLogJpa.NAMESPACE + ".Command";
- protected final static String FQCN = "org.apache.isis.extensions.commandlog.jpa.entities.CommandJpa";
-
- /**
- * Intended for use on primary system.
- *
- * @param command
- */
- public CommandJpa(final Command command) {
-
- setInteractionIdStr(command.getInteractionId().toString());
- setUsername(command.getUsername());
- setTimestamp(command.getTimestamp());
-
- setCommandDto(command.getCommandDto());
- setTarget(command.getTarget());
- setLogicalMemberIdentifier(command.getLogicalMemberIdentifier());
-
- setStartedAt(command.getStartedAt());
- setCompletedAt(command.getCompletedAt());
-
- setResult(command.getResult());
- setException(command.getException());
-
- setReplayState(ReplayState.UNDEFINED);
- }
-
-
- /**
- * Intended for use on secondary (replay) system.
- *
- * @param commandDto - obtained from the primary system as a representation of a command invocation
- * @param replayState - controls whether this is to be replayed
- * @param targetIndex - if the command represents a bulk action, then it is flattened out when replayed; this indicates which target to execute against.
- */
- public CommandJpa(
- final CommandDto commandDto,
- final ReplayState replayState,
- final int targetIndex) {
-
- setInteractionIdStr(commandDto.getInteractionId());
- setUsername(commandDto.getUser());
- setTimestamp(JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(commandDto.getTimestamp()));
-
- setCommandDto(commandDto);
- setTarget(Bookmark.forOidDto(commandDto.getTargets().getOid().get(targetIndex)));
- setLogicalMemberIdentifier(commandDto.getMember().getLogicalMemberIdentifier());
-
- // the hierarchy of commands calling other commands is only available on the primary system, and is
- setParent(null);
-
- setStartedAt(JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(commandDto.getTimings().getStartedAt()));
- setCompletedAt(JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(commandDto.getTimings().getCompletedAt()));
-
- copyOver(commandDto, UserDataKeys.RESULT, value -> this.setResult(Bookmark.parse(value).orElse(null)));
- copyOver(commandDto, UserDataKeys.EXCEPTION, this::setException);
-
- setReplayState(replayState);
- }
-
- static void copyOver(
- final CommandDto commandDto,
- final String key, final Consumer<String> consume) {
- commandDto.getUserData().getEntry()
- .stream()
- .filter(x -> Objects.equals(x.getKey(), key))
- .map(MapDto.Entry::getValue)
- .filter(Objects::nonNull)
- .filter(x -> x.length() > 0)
- .findFirst()
- .ifPresent(consume);
- }
-
- @Service
- public static class TitleProvider {
-
- @EventListener(TitleUiEvent.class)
- public void on(final TitleUiEvent ev) {
- if(!Objects.equals(ev.getTitle(), "Command Jdo") || ev.getTranslatableTitle() != null) {
- return;
- }
- ev.setTitle(title((CommandJpa)ev.getSource()));
- }
-
- private static String title(final CommandJpa source) {
- // nb: not thread-safe
- // formats defined in https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
- val format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
-
- val buf = new TitleBuffer();
- buf.append(format.format(source.getTimestamp()));
- buf.append(" ").append(source.getLogicalMemberIdentifier());
- return buf.toString();
- }
- }
-
-
- public static class InteractionIdDomainEvent extends PropertyDomainEvent<String> { }
- /**
- * Implementation note: persisted as a string rather than a UUID as fails
- * to persist if using h2 (perhaps would need to be mapped differently).
- * @see <a href="https://www.datanucleus.org/products/accessplatform/jdo/mapping.html#_other_types">www.datanucleus.org</a>
- */
-// @javax.jdo.annotations.PrimaryKey
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="false", name = "interactionId", length = 36)
- @Property(domainEvent = InteractionIdDomainEvent.class)
- @PropertyLayout(named = "Interaction Id")
- @Getter @Setter
- private String interactionIdStr;
- @Override
- @Programmatic
- public UUID getInteractionId() {return UUID.fromString(getInteractionIdStr());}
-
-
- public static class UsernameDomainEvent extends PropertyDomainEvent<String> { }
-// @javax.jdo.annotations.Column(allowsNull="false", length = 50)
- @Property(domainEvent = UsernameDomainEvent.class)
- @Getter @Setter
- private String username;
-
-
- public static class TimestampDomainEvent extends PropertyDomainEvent<Timestamp> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="false")
- @Property(domainEvent = TimestampDomainEvent.class)
- @Getter @Setter
- private Timestamp timestamp;
-
-
-
- @Override
- public ChangeType getType() {
- return ChangeType.COMMAND;
- }
-
-
- public static class ReplayStateDomainEvent extends PropertyDomainEvent<ReplayState> { }
- /**
- * For a replayed command, what the outcome was.
- */
-// @javax.jdo.annotations.Column(allowsNull="true", length=10)
- @Property(domainEvent = ReplayStateDomainEvent.class)
- @Getter @Setter
- private ReplayState replayState;
-
-
- public static class ReplayStateFailureReasonDomainEvent extends PropertyDomainEvent<ReplayState> { }
- /**
- * For a {@link ReplayState#FAILED failed} replayed command, what the reason was for the failure.
- */
-// @javax.jdo.annotations.Column(allowsNull="true", length=255)
- @Property(domainEvent = ReplayStateFailureReasonDomainEvent.class)
- @PropertyLayout(hidden = Where.ALL_TABLES, multiLine = 5)
- @Getter @Setter
- private String replayStateFailureReason;
- @MemberSupport public boolean hideReplayStateFailureReason() {
- return getReplayState() == null || !getReplayState().isFailed();
- }
-
-
- public static class ParentDomainEvent extends PropertyDomainEvent<Command> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(name="parentId", allowsNull="true")
- @Property(domainEvent = ParentDomainEvent.class)
- @PropertyLayout(hidden = Where.ALL_TABLES)
- @Getter @Setter
- private CommandJpa parent;
-
-
- public static class TargetDomainEvent extends PropertyDomainEvent<String> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="true", length = 2000, name="target")
- @Property(domainEvent = TargetDomainEvent.class)
- @PropertyLayout(named = "Object")
- @Getter @Setter
- private Bookmark target;
-
- public String getTargetStr() {
- return Optional.ofNullable(getTarget()).map(Bookmark::toString).orElse(null);
- }
-
- @Override
- public String getTargetMember() {
- return getCommandDto().getMember().getLogicalMemberIdentifier();
- }
-
- @Property(domainEvent = TargetDomainEvent.class)
- @PropertyLayout(named = "Member")
- public String getLocalMember() {
- val targetMember = getTargetMember();
- return targetMember.substring(targetMember.indexOf("#") + 1);
- }
-
- public static class LogicalMemberIdentifierDomainEvent extends PropertyDomainEvent<String> { }
- @Property(domainEvent = LogicalMemberIdentifierDomainEvent.class)
- @PropertyLayout(hidden = Where.ALL_TABLES)
-// @javax.jdo.annotations.Column(allowsNull="false", length = MemberIdentifierType.Meta.MAX_LEN)
- @Getter @Setter
- private String logicalMemberIdentifier;
-
-
- public static class CommandDtoDomainEvent extends PropertyDomainEvent<CommandDto> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="true", jdbcType="CLOB")
- @Property(domainEvent = CommandDtoDomainEvent.class)
- @PropertyLayout(multiLine = 9)
- @Getter @Setter
- private CommandDto commandDto;
-
-
- public static class StartedAtDomainEvent extends PropertyDomainEvent<Timestamp> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="true")
- @Property(domainEvent = StartedAtDomainEvent.class)
- @Getter @Setter
- private Timestamp startedAt;
-
-
- public static class CompletedAtDomainEvent extends PropertyDomainEvent<Timestamp> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="true")
- @Property(domainEvent = CompletedAtDomainEvent.class)
- @Getter @Setter
- private Timestamp completedAt;
-
-
- public static class DurationDomainEvent extends PropertyDomainEvent<BigDecimal> { }
- /**
- * The number of seconds (to 3 decimal places) that this interaction lasted.
- *
- * <p>
- * Populated only if it has {@link #getCompletedAt() completed}.
- */
-// @javax.jdo.annotations.NotPersistent
- @javax.validation.constraints.Digits(integer=5, fraction=3)
- @Property(domainEvent = DurationDomainEvent.class)
- public BigDecimal getDuration() {
- return BigDecimalUtils.durationBetween(getStartedAt(), getCompletedAt());
- }
-
-
- public static class IsCompleteDomainEvent extends PropertyDomainEvent<Boolean> { }
-// @javax.jdo.annotations.NotPersistent
- @Property(domainEvent = IsCompleteDomainEvent.class)
- @PropertyLayout(hidden = Where.OBJECT_FORMS)
- public boolean isComplete() {
- return getCompletedAt() != null;
- }
-
-
- public static class ResultSummaryDomainEvent extends PropertyDomainEvent<String> { }
-// @javax.jdo.annotations.NotPersistent
- @Property(domainEvent = ResultSummaryDomainEvent.class)
- @PropertyLayout(hidden = Where.OBJECT_FORMS, named = "Result")
- public String getResultSummary() {
- if(getCompletedAt() == null) {
- return "";
- }
- if(!_Strings.isNullOrEmpty(getException())) {
- return "EXCEPTION";
- }
- if(getResult() != null) {
- return "OK";
- } else {
- return "OK (VOID)";
- }
- }
-
-
- public static class ResultDomainEvent extends PropertyDomainEvent<String> { }
-// @javax.jdo.annotations.Persistent
-// @javax.jdo.annotations.Column(allowsNull="true", length = 2000, name="result")
- @Property(domainEvent = ResultDomainEvent.class)
- @PropertyLayout(hidden = Where.ALL_TABLES, named = "Result Bookmark")
- @Getter @Setter
- private Bookmark result;
-
- public static class ExceptionDomainEvent extends PropertyDomainEvent<String> { }
- /**
- * Stack trace of any exception that might have occurred if this interaction/transaction aborted.
- *
- * <p>
- * Not part of the applib API, because the default implementation is not persistent
- * and so there's no object that can be accessed to be annotated.
- */
-// @javax.jdo.annotations.Column(allowsNull="true", jdbcType="CLOB")
- @Property(domainEvent = ExceptionDomainEvent.class)
- @PropertyLayout(hidden = Where.ALL_TABLES, multiLine = 5, named = "Exception (if any)")
- @Getter
- private String exception;
- public void setException(final String exception) {
- this.exception = exception;
- }
- public void setException(final Throwable exception) {
- setException(_Exceptions.asStacktrace(exception));
- }
-
- public static class IsCausedExceptionDomainEvent extends PropertyDomainEvent<Boolean> { }
-// @javax.jdo.annotations.NotPersistent
- @Property(domainEvent = IsCausedExceptionDomainEvent.class)
- @PropertyLayout(hidden = Where.OBJECT_FORMS)
- public boolean isCausedException() {
- return getException() != null;
- }
-
-
- @Override
- public String getPreValue() {
- return null;
- }
-
- @Override
- public String getPostValue() {
- return null;
- }
-
-
- @Override
- public void saveAnalysis(final String analysis) {
- if (analysis == null) {
- setReplayState(ReplayState.OK);
- } else {
- setReplayState(ReplayState.FAILED);
- setReplayStateFailureReason(StringUtils.trimmed(analysis, 255));
- }
-
- }
-
- @Override
- public String toString() {
- return toFriendlyString();
- }
-
- @Override
- public CommandOutcomeHandler outcomeHandler() {
- return new CommandOutcomeHandler() {
- @Override
- public Timestamp getStartedAt() {
- return CommandJpa.this.getStartedAt();
- }
-
- @Override
- public void setStartedAt(final Timestamp startedAt) {
- CommandJpa.this.setStartedAt(startedAt);
- }
-
- @Override
- public void setCompletedAt(final Timestamp completedAt) {
- CommandJpa.this.setCompletedAt(completedAt);
- }
-
- @Override
- public void setResult(final Result<Bookmark> resultBookmark) {
- CommandJpa.this.setResult(resultBookmark.getValue().orElse(null));
- CommandJpa.this.setException(resultBookmark.getFailure().orElse(null));
- }
-
- };
- }
-
- @Service
- @javax.annotation.Priority(PriorityPrecedence.LATE - 10) // before the framework's own default.
- public static class TableColumnOrderDefault extends TableColumnOrderForCollectionTypeAbstract<CommandJpa> {
-
- public TableColumnOrderDefault() { super(CommandJpa.class); }
-
- @Override
- protected List<String> orderParented(final Object parent, final String collectionId, final List<String> propertyIds) {
- return ordered(propertyIds);
- }
-
- @Override
- protected List<String> orderStandalone(final List<String> propertyIds) {
- return ordered(propertyIds);
- }
-
- private List<String> ordered(final List<String> propertyIds) {
- return Arrays.asList(
- "timestamp", "target", "targetMember", "username", "complete", "resultSummary", "interactionIdStr"
- );
- }
- }
-}
-
diff --git a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/entities/CommandJpaRepository.java b/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/entities/CommandJpaRepository.java
deleted file mode 100644
index f337d44..0000000
--- a/extensions/core/command-log/jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/entities/CommandJpaRepository.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.extensions.commandlog.jpa.entities;
-
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
-
-import org.springframework.lang.Nullable;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.annotation.PriorityPrecedence;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.jaxb.JavaSqlXMLGregorianCalendarMarshalling;
-import org.apache.isis.applib.query.Query;
-import org.apache.isis.applib.query.QueryRange;
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.iactn.InteractionProvider;
-import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.extensions.commandlog.applib.dom.PublishedCommandRepository;
-import org.apache.isis.extensions.commandlog.applib.dom.ReplayState;
-import org.apache.isis.schema.cmd.v2.CommandDto;
-import org.apache.isis.schema.cmd.v2.CommandsDto;
-import org.apache.isis.schema.cmd.v2.MapDto;
-import org.apache.isis.schema.common.v2.InteractionType;
-import org.apache.isis.schema.common.v2.OidDto;
-
-import lombok.RequiredArgsConstructor;
-import lombok.val;
-
-/**
- * Provides supporting functionality for querying and persisting
- * {@link CommandJdo command} entities.
- */
-@Service
-@Named("isis.ext.commandLog.CommandJdoRepository")
-@javax.annotation.Priority(PriorityPrecedence.MIDPOINT)
-@Qualifier("Jpa")
-@RequiredArgsConstructor
-//@Log4j2
-public class CommandJpaRepository
-implements PublishedCommandRepository<CommandJpa> {
-
- @Inject final Provider<InteractionProvider> interactionProviderProvider;
- @Inject final Provider<RepositoryService> repositoryServiceProvider;
-
-
- @Override
- public List<CommandJpa> findByFromAndTo(
- final @Nullable LocalDate from,
- final @Nullable LocalDate to) {
- final Timestamp fromTs = toTimestampStartOfDayWithOffset(from, 0);
- final Timestamp toTs = toTimestampStartOfDayWithOffset(to, 1);
-
- final Query<CommandJpa> query;
- if(from != null) {
- if(to != null) {
- query = Query.named(CommandJpa.class, "findByTimestampBetween")
- .withParameter("from", fromTs)
- .withParameter("to", toTs);
- } else {
- query = Query.named(CommandJpa.class, "findByTimestampAfter")
- .withParameter("from", fromTs);
- }
- } else {
- if(to != null) {
- query = Query.named(CommandJpa.class, "findByTimestampBefore")
- .withParameter("to", toTs);
- } else {
- query = Query.named(CommandJpa.class, "find");
- }
- }
- return repositoryService().allMatches(query);
- }
-
- @Override
- public Optional<CommandJpa> findByInteractionId(final UUID interactionId) {
- return repositoryService().firstMatch(
- Query.named(CommandJpa.class, "findByInteractionIdStr")
- .withParameter("interactionIdStr", interactionId.toString()));
- }
-
- @Override
- public List<CommandJpa> findByParent(final CommandModel parent) {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findByParent")
- .withParameter("parent", parent));
- }
-
- @Override
- public List<CommandJpa> findCurrent() {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findCurrent"));
- }
-
- @Override
- public List<CommandJpa> findCompleted() {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findCompleted"));
- }
-
- @Override
- public List<CommandJpa> findByTargetAndFromAndTo(
- final Bookmark target,
- final @Nullable LocalDate from,
- final @Nullable LocalDate to) {
-
- final Timestamp fromTs = toTimestampStartOfDayWithOffset(from, 0);
- final Timestamp toTs = toTimestampStartOfDayWithOffset(to, 1);
-
- final Query<CommandJpa> query;
- if(from != null) {
- if(to != null) {
- query = Query.named(CommandJpa.class, "findByTargetAndTimestampBetween")
- .withParameter("target", target)
- .withParameter("from", fromTs)
- .withParameter("to", toTs);
- } else {
- query = Query.named(CommandJpa.class, "findByTargetAndTimestampAfter")
- .withParameter("target", target)
- .withParameter("from", fromTs);
- }
- } else {
- if(to != null) {
- query = Query.named(CommandJpa.class, "findByTargetAndTimestampBefore")
- .withParameter("target", target)
- .withParameter("to", toTs);
- } else {
- query = Query.named(CommandJpa.class, "findByTarget")
- .withParameter("target", target);
- }
- }
- return repositoryService().allMatches(query);
- }
-
- private static Timestamp toTimestampStartOfDayWithOffset(
- final @Nullable LocalDate dt,
- final int daysOffset) {
-
- return dt!=null
- ? new java.sql.Timestamp(
- Instant.from(dt.atStartOfDay().plusDays(daysOffset).atZone(ZoneId.systemDefault()))
- .toEpochMilli())
- : null;
- }
-
- @Override
- public List<CommandJpa> findRecentByUsername(final String username) {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findRecentByUsername")
- .withParameter("username", username));
- }
-
- @Override
- public List<CommandJpa> findRecentByTarget(final Bookmark target) {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findRecentByTarget")
- .withParameter("target", target));
- }
-
- @Override
- public List<CommandJpa> findSince(final UUID interactionId, final Integer batchSize) {
- if(interactionId == null) {
- return findFirst();
- }
- final CommandJpa from = findByInteractionIdElseNull(interactionId);
- if(from == null) {
- return Collections.emptyList();
- }
- return findSince(from.getTimestamp(), batchSize);
- }
-
- private List<CommandJpa> findFirst() {
- Optional<CommandJpa> firstCommandIfAny = repositoryService().firstMatch(
- Query.named(CommandJpa.class, "findFirst"));
- return firstCommandIfAny
- .map(Collections::singletonList)
- .orElse(Collections.emptyList());
- }
-
-
- private CommandJpa findByInteractionIdElseNull(final UUID interactionId) {
- return null;
- //TODO migrate to JPA
-// val tsq = jdoSupport.newTypesafeQuery(CommandJpa.class);
-// val cand = QCommandJdo.candidate();
-// val q = tsq.filter(
-// cand.interactionIdStr.eq(tsq.parameter("interactionIdStr", String.class))
-// );
-// q.setParameter("interactionIdStr", interactionId.toString());
-// return q.executeUnique();
- }
-
- private List<CommandJpa> findSince(
- final Timestamp timestamp,
- final Integer batchSize) {
-
- // DN generates incorrect SQL for SQL Server if count set to 1; so we set to 2 and then trim
- // XXX that's a historic workaround, should rather be fixed upstream
- val needsTrimFix = batchSize != null && batchSize == 1;
-
- val q = Query.named(CommandJpa.class, "findSince")
- .withParameter("timestamp", timestamp)
- .withRange(QueryRange.limit(
- needsTrimFix ? 2L : batchSize
- ));
-
- final List<CommandJpa> commandJdos = repositoryService().allMatches(q);
- return needsTrimFix && commandJdos.size() > 1
- ? commandJdos.subList(0,1)
- : commandJdos;
- }
-
-
- @Override
- public Optional<CommandJpa> findMostRecentReplayed() {
-
- return repositoryService().firstMatch(
- Query.named(CommandJpa.class, "findMostRecentReplayed"));
- }
-
- @Override
- public Optional<CommandJpa> findMostRecentCompleted() {
- return repositoryService().firstMatch(
- Query.named(CommandJpa.class, "findMostRecentCompleted"));
- }
-
- @Override
- public List<CommandJpa> findNotYetReplayed() {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findNotYetReplayed"));
- }
-
- @Override
- public List<CommandJpa> findReplayedOnSecondary() {
- return repositoryService().allMatches(
- Query.named(CommandJpa.class, "findReplayableMostRecentStarted"));
- }
-
- @Override
- public List<CommandJpa> saveForReplay(final CommandsDto commandsDto) {
- List<CommandDto> commandDto = commandsDto.getCommandDto();
- List<CommandJpa> commands = new ArrayList<>();
- for (final CommandDto dto : commandDto) {
- commands.add(saveForReplay(dto));
- }
- return commands;
- }
-
- @Programmatic
- @Override
- public CommandJpa saveForReplay(final CommandDto dto) {
-
- if(dto.getMember().getInteractionType() == InteractionType.ACTION_INVOCATION) {
- final MapDto userData = dto.getUserData();
- if (userData == null ) {
- throw new IllegalStateException(String.format(
- "Can only persist action DTOs with additional userData; got: \n%s",
- CommandDtoUtils.toXml(dto)));
- }
- }
-
- final CommandJpa commandJdo = new CommandJpa();
-
- commandJdo.setInteractionIdStr(dto.getInteractionId());
- commandJdo.setTimestamp(JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(dto.getTimestamp()));
- commandJdo.setUsername(dto.getUser());
-
- commandJdo.setReplayState(ReplayState.PENDING);
-
- final OidDto firstTarget = dto.getTargets().getOid().get(0);
- commandJdo.setTarget(Bookmark.forOidDto(firstTarget));
- commandJdo.setCommandDto(dto);
- commandJdo.setLogicalMemberIdentifier(dto.getMember().getLogicalMemberIdentifier());
-
- persist(commandJdo);
-
- return commandJdo;
- }
-
- @Override
- public void persist(final CommandJpa commandJdo) {
- repositoryService().persist(commandJdo);
- }
-
- @Override
- public void truncateLog() {
- repositoryService().removeAll(CommandJpa.class);
- }
-
- private RepositoryService repositoryService() {
- return repositoryServiceProvider.get();
- }
-
-}
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/role/dom/ApplicationRole.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/role/dom/ApplicationRole.java
index a2c8d94..08dc094 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/role/dom/ApplicationRole.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/role/dom/ApplicationRole.java
@@ -41,30 +41,28 @@ import org.apache.isis.applib.annotation.DomainObjectLayout;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUser;
-
@PersistenceCapable(
identityType = IdentityType.DATASTORE,
schema = "isisExtensionsSecman",
table = "ApplicationRole")
-@Inheritance(
- strategy = InheritanceStrategy.NEW_TABLE)
-@DatastoreIdentity(
- strategy = IdGeneratorStrategy.NATIVE, column = "id")
@Uniques({
- @Unique(
- name = "ApplicationRole_name_UNQ", members = { "name" })
+ @Unique(
+ name = "ApplicationRole_name_UNQ",
+ members = { "name" })
})
+@Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
+@DatastoreIdentity(strategy = IdGeneratorStrategy.NATIVE, column = "id")
@Queries({
- @Query(
- name = org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole.NAMED_QUERY_FIND_BY_NAME,
- value = "SELECT "
- + "FROM " + ApplicationRole.FQCN
- + " WHERE name == :name"),
- @Query(
- name = org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole.NAMED_QUERY_FIND_BY_NAME_CONTAINING,
- value = "SELECT "
- + "FROM " + ApplicationRole.FQCN
- + " WHERE name.matches(:regex) ")
+ @Query(
+ name = org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole.NAMED_QUERY_FIND_BY_NAME,
+ value = "SELECT "
+ + "FROM " + ApplicationRole.FQCN
+ + " WHERE name == :name"),
+ @Query(
+ name = org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole.NAMED_QUERY_FIND_BY_NAME_CONTAINING,
+ value = "SELECT "
+ + "FROM " + ApplicationRole.FQCN
+ + " WHERE name.matches(:regex) ")
})
@DomainObject(
bounding = Bounding.BOUNDED,
@@ -76,7 +74,7 @@ import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUser;
bookmarking = BookmarkPolicy.AS_ROOT
)
public class ApplicationRole
- extends org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole {
+ extends org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole {
protected final static String FQCN = "org.apache.isis.extensions.secman.jdo.role.dom.ApplicationRole";
@@ -131,3 +129,4 @@ public class ApplicationRole
}
+
diff --git a/persistence/jdo/adoc/modules/ROOT/pages/hints-and-tips/jdoql-and-timestamps.adoc b/persistence/jdo/adoc/modules/ROOT/pages/hints-and-tips/jdoql-and-timestamps.adoc
index fe6586f..ce1f539 100644
--- a/persistence/jdo/adoc/modules/ROOT/pages/hints-and-tips/jdoql-and-timestamps.adoc
+++ b/persistence/jdo/adoc/modules/ROOT/pages/hints-and-tips/jdoql-and-timestamps.adoc
@@ -6,7 +6,7 @@
Beware of entities with a property called "timestamp": you run the risk of "timestamp" being treated as a keyword in certain contexts, probably not as you intended.
-By way of example, the xref:userguide:command-log:about.adoc[Command Log] module has an entity called `PublishedCommandForJdo`.
+By way of example, the xref:userguide:command-log:about.adoc[Command Log] module has an entity called `PublishedCommand`.
This has a property called "timestamp", of type `java.sql.Timestamp`.
This defines a query using JDOQL: