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 2016/05/01 13:16:49 UTC
[1/3] isis git commit: ISIS-1370: factored out
AuditingServiceInternal as wrapper around AuditingService3 (similar design to
PublshingServiceInternal wrapping PublishingService).
Repository: isis
Updated Branches:
refs/heads/ISIS-1291 9d8847fc3 -> ad43cad3f
ISIS-1370: factored out AuditingServiceInternal as wrapper around AuditingService3 (similar design to PublshingServiceInternal wrapping PublishingService).
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/5870f6a5
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/5870f6a5
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/5870f6a5
Branch: refs/heads/ISIS-1291
Commit: 5870f6a5973fd65af8d054ffe872f24b80fbdefc
Parents: 9d8847f
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun May 1 11:22:50 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun May 1 11:22:50 2016 +0100
----------------------------------------------------------------------
.../publishing/AuditingServiceInternal.java | 117 +++++++++++++++++++
.../system/transaction/IsisTransaction.java | 91 +++------------
2 files changed, 135 insertions(+), 73 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/5870f6a5/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java
new file mode 100644
index 0000000..3f29804
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java
@@ -0,0 +1,117 @@
+/*
+ * 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.core.runtime.services.publishing;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.audit.AuditingService3;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.clock.ClockService;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.user.UserService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
+import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+
+/**
+ * Wrapper around {@link org.apache.isis.applib.services.audit.AuditingService3}. Is a no-op if there is no injected service.
+ */
+@DomainService(nature = NatureOfService.DOMAIN)
+public class AuditingServiceInternal {
+
+
+ @Programmatic
+ public boolean canAudit() {
+ return auditingServiceIfAny != null;
+ }
+
+ @Programmatic
+ public void audit(
+ final Set<Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues>> changedObjectProperties) {
+
+ if(!canAudit()) {
+ return;
+ }
+
+ final String currentUser = userService.getUser().getName();
+ final java.sql.Timestamp currentTime = clockService.nowAsJavaSqlTimestamp();
+
+ for (Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry : changedObjectProperties) {
+ auditChangedProperty(currentTime, currentUser, auditEntry);
+ }
+
+ }
+
+ private void auditChangedProperty(
+ final java.sql.Timestamp timestamp,
+ final String user,
+ final Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry) {
+
+ final IsisTransaction.AdapterAndProperty aap = auditEntry.getKey();
+ final ObjectAdapter adapter = aap.getAdapter();
+
+ final AuditableFacet auditableFacet = adapter.getSpecification().getFacet(AuditableFacet.class);
+ if(auditableFacet == null || auditableFacet.isDisabled()) {
+ return;
+ }
+
+ final Bookmark target = aap.getBookmark();
+ final String propertyId = aap.getPropertyId();
+ final String memberId = aap.getMemberId();
+
+ final IsisTransaction.PreAndPostValues papv = auditEntry.getValue();
+ final String preValue = papv.getPreString();
+ final String postValue = papv.getPostString();
+
+
+ final String targetClass = CommandUtil.targetClassNameFor(adapter);
+
+ final Command command = commandContext.getCommand();
+ final UUID transactionId = command.getTransactionId();
+
+ auditingServiceIfAny
+ .audit(transactionId, targetClass, target, memberId, propertyId, preValue, postValue, user, timestamp);
+ }
+
+ /**
+ * could be null if none has been registered.
+ */
+ @Inject
+ private AuditingService3 auditingServiceIfAny;
+
+ @Inject
+ UserService userService;
+
+ @Inject
+ ClockService clockService;
+
+ @Inject
+ CommandContext commandContext;
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/5870f6a5/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
index 0f2747e..99b3079 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
@@ -41,9 +41,7 @@ import org.slf4j.LoggerFactory;
import org.apache.isis.applib.annotation.Bulk;
import org.apache.isis.applib.annotation.PublishedObject.ChangeKind;
-import org.apache.isis.applib.clock.Clock;
import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
-import org.apache.isis.applib.services.audit.AuditingService3;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.command.Command2;
@@ -60,8 +58,6 @@ import org.apache.isis.core.commons.util.ToString;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
-import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
import org.apache.isis.core.metamodel.services.publishing.PublishingServiceInternal;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
@@ -70,6 +66,7 @@ import org.apache.isis.core.metamodel.transactions.TransactionState;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
+import org.apache.isis.core.runtime.services.publishing.AuditingServiceInternal;
import org.apache.isis.core.runtime.system.context.IsisContext;
import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
@@ -219,11 +216,8 @@ public class IsisTransaction implements TransactionScopedComponent {
private final InteractionContext interactionContext;
private final PublishingServiceInternal publishingServiceInternal;
+ private final AuditingServiceInternal auditingServiceInternal;
- /**
- * could be null if none has been registered.
- */
- private final AuditingService3 auditingServiceIfAny;
private final UUID transactionId;
@@ -252,8 +246,8 @@ public class IsisTransaction implements TransactionScopedComponent {
this.interactionContext = lookupService(InteractionContext.class);
- this.auditingServiceIfAny = lookupServiceIfAny(AuditingService3.class);
this.publishingServiceInternal = lookupService(PublishingServiceInternal.class);
+ this.auditingServiceInternal = lookupService(AuditingServiceInternal.class);
this.transactionId = transactionId;
@@ -419,53 +413,6 @@ public class IsisTransaction implements TransactionScopedComponent {
}
- protected void doAudit(final Set<Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties) {
- try {
- if(auditingServiceIfAny == null) {
- return;
- }
-
- // else
- final String currentUser = getTransactionManager().getAuthenticationSession().getUserName();
- final java.sql.Timestamp currentTime = Clock.getTimeAsJavaSqlTimestamp();
- for (Entry<AdapterAndProperty, PreAndPostValues> auditEntry : changedObjectProperties) {
- auditChangedProperty(currentTime, currentUser, auditEntry);
- }
-
- } finally {
- // not needed in production, but is required for integration testing
- this.changedObjectProperties.clear();
- }
- }
-
- public void auditChangedProperty(
- final java.sql.Timestamp timestamp,
- final String user,
- final Entry<AdapterAndProperty, PreAndPostValues> auditEntry) {
-
- final AdapterAndProperty aap = auditEntry.getKey();
- final ObjectAdapter adapter = aap.getAdapter();
-
- final AuditableFacet auditableFacet = adapter.getSpecification().getFacet(AuditableFacet.class);
- if(auditableFacet == null || auditableFacet.isDisabled()) {
- return;
- }
-
- final Bookmark target = aap.getBookmark();
- final String propertyId = aap.getPropertyId();
- final String memberId = aap.getMemberId();
-
- final PreAndPostValues papv = auditEntry.getValue();
- final String preValue = papv.getPreString();
- final String postValue = papv.getPostString();
-
-
- final String targetClass = CommandUtil.targetClassNameFor(adapter);
-
- auditingServiceIfAny
- .audit(getTransactionId(), targetClass, target, memberId, propertyId, preValue, postValue, user, timestamp);
- }
-
private static String asString(Object object) {
return object != null? object.toString(): null;
}
@@ -525,7 +472,21 @@ public class IsisTransaction implements TransactionScopedComponent {
ensureCommandsPersistedIfDirtyXactn(changedObjectProperties);
- preCommitServices(changedObjectProperties);
+ try {
+ auditingServiceInternal.audit(changedObjectProperties);
+ } finally {
+ // not needed in production, but is required for integration testing
+ this.changedObjectProperties.clear();
+ }
+
+ publishingServiceInternal.publishObjects(this.changeKindByEnlistedAdapter);
+ doFlush();
+
+ closeOtherApplibServicesIfConfigured();
+
+ completeCommandAndInteractionAndClearDomainEvents();
+ doFlush();
+
} catch (final RuntimeException ex) {
setAbortCause(new IsisTransactionManagerException(ex));
@@ -557,22 +518,6 @@ public class IsisTransaction implements TransactionScopedComponent {
Predicates.not(IS_COMMAND)));
}
-
- private void preCommitServices(
- final Set<Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties) {
-
- doAudit(changedObjectProperties);
-
- publishingServiceInternal.publishObjects(this.changeKindByEnlistedAdapter);
- doFlush();
-
- closeOtherApplibServicesIfConfigured();
-
- completeCommandAndInteractionAndClearDomainEvents();
-
- doFlush();
- }
-
private void closeOtherApplibServicesIfConfigured() {
final ActionInvocationContext actionInvocationContext = lookupService(ActionInvocationContext.class);
if(actionInvocationContext != null) {
[3/3] isis git commit: ISIS-1370: factored out
EnlistedObjectsServiceInternal from IsisTransaction;
used by AuditingServiceInternal and PublishingServiceInternal(Default).
Posted by da...@apache.org.
ISIS-1370: factored out EnlistedObjectsServiceInternal from IsisTransaction; used by AuditingServiceInternal and PublishingServiceInternal(Default).
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/ad43cad3
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/ad43cad3
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/ad43cad3
Branch: refs/heads/ISIS-1291
Commit: ad43cad3fc029d2b9f90232d7fc270bbbe30eb7e
Parents: e2fb62e
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun May 1 12:16:39 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun May 1 12:16:39 2016 +0100
----------------------------------------------------------------------
.../publishing/PublishingServiceInternal.java | 7 +-
.../auditing/AuditingServiceInternal.java | 40 +-
.../services/enlist/AdapterAndProperty.java | 125 ++++++
.../enlist/EnlistedObjectsServiceInternal.java | 256 +++++++++++
.../services/enlist/PreAndPostValues.java | 104 +++++
.../PublishingServiceInternalDefault.java | 16 +-
.../system/persistence/PersistenceSession.java | 18 +-
.../system/transaction/IsisTransaction.java | 437 +------------------
8 files changed, 557 insertions(+), 446 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/publishing/PublishingServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/publishing/PublishingServiceInternal.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/publishing/PublishingServiceInternal.java
index 036731f..b0ed8c1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/publishing/PublishingServiceInternal.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/publishing/PublishingServiceInternal.java
@@ -19,21 +19,19 @@
package org.apache.isis.core.metamodel.services.publishing;
import java.util.List;
-import java.util.Map;
import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.PublishedObject;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
public interface PublishingServiceInternal {
+
@Programmatic
boolean canPublish();
@Programmatic
- void publishObjects(
- final Map<ObjectAdapter, PublishedObject.ChangeKind> changeKindByEnlistedAdapter);
+ void publishObjects();
@Programmatic
void publishAction(
@@ -42,5 +40,4 @@ public interface PublishingServiceInternal {
final ObjectAdapter targetAdapter,
final List<ObjectAdapter> parameterAdapters,
final ObjectAdapter resultAdapter);
-
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
index a470946..35874de 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
@@ -36,7 +36,9 @@ import org.apache.isis.applib.services.user.UserService;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
-import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+import org.apache.isis.core.runtime.services.enlist.AdapterAndProperty;
+import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceInternal;
+import org.apache.isis.core.runtime.services.enlist.PreAndPostValues;
/**
* Wrapper around {@link org.apache.isis.applib.services.audit.AuditingService3}. Is a no-op if there is no injected service.
@@ -51,28 +53,34 @@ public class AuditingServiceInternal {
}
@Programmatic
- public void audit(
- final Set<Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues>> changedObjectProperties) {
+ public void audit() {
+ final Set<Map.Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties =
+ enlistedObjectsServiceInternal.getChangedObjectProperties();
- if(!canAudit()) {
- return;
- }
+ try {
+ if(!canAudit()) {
+ return;
+ }
- final String currentUser = userService.getUser().getName();
- final java.sql.Timestamp currentTime = clockService.nowAsJavaSqlTimestamp();
+ final String currentUser = userService.getUser().getName();
+ final java.sql.Timestamp currentTime = clockService.nowAsJavaSqlTimestamp();
- for (Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry : changedObjectProperties) {
- auditChangedProperty(currentTime, currentUser, auditEntry);
- }
+ for (Map.Entry<AdapterAndProperty, PreAndPostValues> auditEntry : changedObjectProperties) {
+ auditChangedProperty(currentTime, currentUser, auditEntry);
+ }
+ } finally {
+ // not needed in production, but is required for integration testing
+ enlistedObjectsServiceInternal.clearChangedObjectProperties();
+ }
}
private void auditChangedProperty(
final java.sql.Timestamp timestamp,
final String user,
- final Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry) {
+ final Map.Entry<AdapterAndProperty, PreAndPostValues> auditEntry) {
- final IsisTransaction.AdapterAndProperty aap = auditEntry.getKey();
+ final AdapterAndProperty aap = auditEntry.getKey();
final ObjectAdapter adapter = aap.getAdapter();
final AuditableFacet auditableFacet = adapter.getSpecification().getFacet(AuditableFacet.class);
@@ -84,7 +92,7 @@ public class AuditingServiceInternal {
final String propertyId = aap.getPropertyId();
final String memberId = aap.getMemberId();
- final IsisTransaction.PreAndPostValues papv = auditEntry.getValue();
+ final PreAndPostValues papv = auditEntry.getValue();
final String preValue = papv.getPreString();
final String postValue = papv.getPostString();
@@ -105,6 +113,9 @@ public class AuditingServiceInternal {
private AuditingService3 auditingServiceIfAny;
@Inject
+ private EnlistedObjectsServiceInternal enlistedObjectsServiceInternal;
+
+ @Inject
UserService userService;
@Inject
@@ -113,5 +124,4 @@ public class AuditingServiceInternal {
@Inject
CommandContext commandContext;
-
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/AdapterAndProperty.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/AdapterAndProperty.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/AdapterAndProperty.java
new file mode 100644
index 0000000..ef39483
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/AdapterAndProperty.java
@@ -0,0 +1,125 @@
+/*
+ * 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.core.runtime.services.enlist;
+
+import java.util.Map;
+
+import com.google.common.base.Function;
+
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+
+public class AdapterAndProperty {
+
+ private final ObjectAdapter objectAdapter;
+ private final ObjectAssociation property;
+ private final Bookmark bookmark;
+ private final String propertyId;
+ private final String bookmarkStr;
+
+ public static AdapterAndProperty of(ObjectAdapter adapter, ObjectAssociation property) {
+ return new AdapterAndProperty(adapter, property);
+ }
+
+ private AdapterAndProperty(ObjectAdapter adapter, ObjectAssociation property) {
+ this.objectAdapter = adapter;
+ this.property = property;
+
+ final RootOid oid = (RootOid) adapter.getOid();
+
+ final String objectType = oid.getObjectSpecId().asString();
+ final String identifier = oid.getIdentifier();
+ bookmark = new Bookmark(objectType, identifier);
+ bookmarkStr = bookmark.toString();
+
+ propertyId = property.getId();
+ }
+
+ public ObjectAdapter getAdapter() {
+ return objectAdapter;
+ }
+
+ public ObjectAssociation getProperty() {
+ return property;
+ }
+
+ public Bookmark getBookmark() {
+ return bookmark;
+ }
+
+ public String getPropertyId() {
+ return propertyId;
+ }
+
+ public String getMemberId() {
+ return property.getIdentifier().toClassAndNameIdentityString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ final AdapterAndProperty that = (AdapterAndProperty) o;
+
+ if (bookmarkStr != null ? !bookmarkStr.equals(that.bookmarkStr) : that.bookmarkStr != null)
+ return false;
+ if (propertyId != null ? !propertyId.equals(that.propertyId) : that.propertyId != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = propertyId != null ? propertyId.hashCode() : 0;
+ result = 31 * result + (bookmarkStr != null ? bookmarkStr.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return bookmarkStr + " , " + getProperty().getId();
+ }
+
+ public Object getPropertyValue() {
+ ObjectAdapter referencedAdapter = property.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK);
+ return referencedAdapter == null ? null : referencedAdapter.getObject();
+ }
+
+ static class Functions {
+ private Functions() {
+ }
+
+ static final Function<Map.Entry<AdapterAndProperty, PreAndPostValues>, ObjectAdapter> GET_ADAPTER = new Function<Map.Entry<AdapterAndProperty, PreAndPostValues>, ObjectAdapter>() {
+ @Override
+ public ObjectAdapter apply(Map.Entry<AdapterAndProperty, PreAndPostValues> input) {
+ final AdapterAndProperty aap = input.getKey();
+ return aap.getAdapter();
+ }
+ };
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
new file mode 100644
index 0000000..1839b6e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
@@ -0,0 +1,256 @@
+/*
+ * 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.core.runtime.services.enlist;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.enterprise.context.RequestScoped;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+
+@DomainService(nature = NatureOfService.DOMAIN)
+@RequestScoped
+public class EnlistedObjectsServiceInternal {
+
+ // used for auditing
+ private final Map<AdapterAndProperty, PreAndPostValues> changedObjectProperties = Maps.newLinkedHashMap();
+
+ // used for publishing
+ private final Map<ObjectAdapter,PublishedObject.ChangeKind> changeKindByEnlistedAdapter = Maps.newLinkedHashMap();
+
+ /**
+ * Auditing and publishing support: for object stores to enlist an object that has just been created,
+ * capturing a dummy value <tt>'[NEW]'</tt> for the pre-modification value.
+ *
+ * <p>
+ * The post-modification values are captured when the transaction commits.
+ *
+ * <p>
+ * Supported by the JDO object store; check documentation for support in other objectstores.
+ */
+ @Programmatic
+ public void enlistCreated(final ObjectAdapter adapter) {
+
+ enlistForPublishing(adapter, PublishedObject.ChangeKind.CREATE);
+
+ for (ObjectAssociation property : adapter.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES)) {
+ final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
+ if(property.isNotPersisted()) {
+ continue;
+ }
+ if(changedObjectProperties.containsKey(aap)) {
+ // already enlisted, so ignore
+ return;
+ }
+ PreAndPostValues papv = PreAndPostValues.pre(IsisTransaction.Placeholder.NEW);
+ changedObjectProperties.put(aap, papv);
+ }
+ }
+
+ /**
+ * Auditing and publishing support: for object stores to enlist an object that is about to be updated,
+ * capturing the pre-modification values of the properties of the {@link ObjectAdapter}.
+ *
+ * <p>
+ * The post-modification values are captured when the transaction commits.
+ *
+ * <p>
+ * Supported by the JDO object store; check documentation for support in other objectstores.
+ */
+ @Programmatic
+ public void enlistUpdating(final ObjectAdapter adapter) {
+
+ enlistForPublishing(adapter, PublishedObject.ChangeKind.UPDATE);
+
+ for (ObjectAssociation property : adapter.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES)) {
+ final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
+ if(property.isNotPersisted()) {
+ continue;
+ }
+ if(changedObjectProperties.containsKey(aap)) {
+ // already enlisted, so ignore
+ return;
+ }
+ PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
+ changedObjectProperties.put(aap, papv);
+ }
+ }
+
+ /**
+ * Auditing and publishing support: for object stores to enlist an object that is about to be deleted,
+ * capturing the pre-deletion value of the properties of the {@link ObjectAdapter}.
+ *
+ * <p>
+ * The post-modification values are captured when the transaction commits. In the case of deleted objects, a
+ * dummy value <tt>'[DELETED]'</tt> is used as the post-modification value.
+ *
+ * <p>
+ * Supported by the JDO object store; check documentation for support in other objectstores.
+ */
+ @Programmatic
+ public void enlistDeleting(final ObjectAdapter adapter) {
+
+ final boolean enlisted = enlistForPublishing(adapter, PublishedObject.ChangeKind.DELETE);
+ if(!enlisted) {
+ return;
+ }
+
+ for (ObjectAssociation property : adapter.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES)) {
+ final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
+ if(property.isNotPersisted()) {
+ continue;
+ }
+ if(changedObjectProperties.containsKey(aap)) {
+ // already enlisted, so ignore
+ return;
+ }
+ PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
+ changedObjectProperties.put(aap, papv);
+ }
+ }
+
+
+ /**
+ *
+ * @param adapter
+ * @param current
+ * @return <code>true</code> if successfully enlisted, <code>false</code> if was already enlisted
+ */
+ private boolean enlistForPublishing(final ObjectAdapter adapter, final PublishedObject.ChangeKind current) {
+ final PublishedObject.ChangeKind previous = changeKindByEnlistedAdapter.get(adapter);
+ if(previous == null) {
+ changeKindByEnlistedAdapter.put(adapter, current);
+ return true;
+ }
+ switch (previous) {
+ case CREATE:
+ switch (current) {
+ case DELETE:
+ changeKindByEnlistedAdapter.remove(adapter);
+ case CREATE:
+ case UPDATE:
+ return false;
+ }
+ break;
+ case UPDATE:
+ switch (current) {
+ case DELETE:
+ changeKindByEnlistedAdapter.put(adapter, current);
+ return true;
+ case CREATE:
+ case UPDATE:
+ return false;
+ }
+ break;
+ case DELETE:
+ return false;
+ }
+ return previous == null;
+ }
+
+
+ @Programmatic
+ public boolean hasChangedAdapters() {
+ final Set<Map.Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties = getChangedObjectProperties();
+
+ final Set<ObjectAdapter> changedAdapters = Sets.newHashSet(
+ Iterables.filter(
+ Iterables.transform(
+ changedObjectProperties,
+ AdapterAndProperty.Functions.GET_ADAPTER),
+ Predicates.not(IS_COMMAND)));
+ return !changedAdapters.isEmpty();
+ }
+
+ private static final Predicate<ObjectAdapter> IS_COMMAND = new Predicate<ObjectAdapter>() {
+ @Override
+ public boolean apply(ObjectAdapter input) {
+ return Command.class.isAssignableFrom(input.getSpecification().getCorrespondingClass());
+ }
+ };
+
+ @Programmatic
+ public Set<Map.Entry<AdapterAndProperty, PreAndPostValues>> getChangedObjectProperties() {
+ final Map<AdapterAndProperty, PreAndPostValues> processedObjectProperties = getAdapterAndPropertyPreAndPostValuesMap();
+
+ return Collections.unmodifiableSet(
+ Sets.filter(processedObjectProperties.entrySet(), PreAndPostValues.Predicates.CHANGED));
+ }
+
+ private Map<AdapterAndProperty, PreAndPostValues> getAdapterAndPropertyPreAndPostValuesMap() {
+ final Map<AdapterAndProperty, PreAndPostValues> processedObjectProperties = Maps.newLinkedHashMap();
+
+ while(!changedObjectProperties.isEmpty()) {
+
+ final Set<AdapterAndProperty> keys = Sets.newLinkedHashSet(changedObjectProperties.keySet());
+ for (final AdapterAndProperty aap : keys) {
+
+ final PreAndPostValues papv = changedObjectProperties.remove(aap);
+
+ final ObjectAdapter adapter = aap.getAdapter();
+ if(adapter.isDestroyed()) {
+ // don't touch the object!!!
+ // JDO, for example, will complain otherwise...
+ papv.setPost(IsisTransaction.Placeholder.DELETED);
+ } else {
+ papv.setPost(aap.getPropertyValue());
+ }
+
+ // if we encounter the same objectProperty again, this will simply overwrite it
+ processedObjectProperties.put(aap, papv);
+ }
+ }
+ return processedObjectProperties;
+ }
+
+ @Programmatic
+ public void clearChangedObjectProperties() {
+ changedObjectProperties.clear();
+ }
+
+
+ @Programmatic
+ public Map<ObjectAdapter, PublishedObject.ChangeKind> getChangeKindByEnlistedAdapter() {
+ return changeKindByEnlistedAdapter;
+ }
+
+
+ static String asString(Object object) {
+ return object != null? object.toString(): null;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/PreAndPostValues.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/PreAndPostValues.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/PreAndPostValues.java
new file mode 100644
index 0000000..c9d59be
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/PreAndPostValues.java
@@ -0,0 +1,104 @@
+/*
+ * 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.core.runtime.services.enlist;
+
+import java.util.Map;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+
+public class PreAndPostValues {
+
+ public static class Predicates {
+ public final static Predicate<Map.Entry<?, PreAndPostValues>> CHANGED = new Predicate<Map.Entry<?, PreAndPostValues>>() {
+ @Override
+ public boolean apply(Map.Entry<?, PreAndPostValues> input) {
+ final PreAndPostValues papv = input.getValue();
+ return papv.differ();
+ }
+ };
+ }
+
+ private final Object pre;
+ /**
+ * Eagerly calculated because it could be that the object referenced ends up being deleted by the time that the xactn completes.
+ */
+ private final String preString;
+
+ /**
+ * Updated in {@link #setPost(Object)}
+ */
+ private Object post;
+ /**
+ * Updated in {@link #setPost(Object)}, along with {@link #post}.
+ */
+ private String postString;
+
+ public static PreAndPostValues pre(Object preValue) {
+ return new PreAndPostValues(preValue, null);
+ }
+
+ private PreAndPostValues(Object pre, Object post) {
+ this.pre = pre;
+ this.post = post;
+ this.preString = EnlistedObjectsServiceInternal.asString(pre);
+ }
+
+ /**
+ * The object that was referenced before this object was changed
+ * <p/>
+ * <p/>
+ * Note that this referenced object itself could end up being deleted in the course of the transaction; in which case use
+ * {@link #getPreString()} which is the eagerly cached <tt>toString</tt> of said object.
+ */
+ public Object getPre() {
+ return pre;
+ }
+
+ public String getPreString() {
+ return preString;
+ }
+
+ public Object getPost() {
+ return post;
+ }
+
+ public String getPostString() {
+ return postString;
+ }
+
+ public void setPost(Object post) {
+ this.post = post;
+ this.postString = EnlistedObjectsServiceInternal.asString(post);
+ }
+
+ @Override
+ public String toString() {
+ return getPre() + " -> " + getPost();
+ }
+
+ public boolean differ() {
+ if (getPre() == IsisTransaction.Placeholder.NEW || getPost() == IsisTransaction.Placeholder.DELETED) {
+ return true;
+ }
+ return !Objects.equal(getPre(), getPost());
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
index b860d2b..8d5441d 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
@@ -62,6 +62,7 @@ import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
import org.apache.isis.core.metamodel.facets.object.publishedobject.PublishedObjectFacet;
import org.apache.isis.core.metamodel.services.publishing.PublishingServiceInternal;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceInternal;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
@@ -107,18 +108,23 @@ public class PublishingServiceInternalDefault implements PublishingServiceIntern
throw new IllegalArgumentException("unknown ChangeKind '" + changeKind + "'");
}
- @Override @Programmatic
+ @Override
+ @Programmatic
public boolean canPublish() {
return publishingServiceIfAny != null;
}
- @Override @Programmatic
- public void publishObjects(final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter) {
+ @Override
+ @Programmatic
+ public void publishObjects() {
if(!canPublish()) {
return;
}
+ final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter =
+ enlistedObjectsServiceInternal.getChangeKindByEnlistedAdapter();
+
final String currentUser = userService.getUser().getName();
final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
final ObjectStringifier stringifier = objectStringifier();
@@ -234,6 +240,7 @@ public class PublishingServiceInternalDefault implements PublishingServiceIntern
publishingServiceIfAny.publish(metadata, payload);
}
+
private static <T> List<T> immutableList(final Iterable<T> iterable) {
return Collections.unmodifiableList(Lists.newArrayList(iterable));
}
@@ -301,6 +308,9 @@ public class PublishingServiceInternalDefault implements PublishingServiceIntern
private PublishingService publishingServiceIfAny;
@Inject
+ private EnlistedObjectsServiceInternal enlistedObjectsServiceInternal;
+
+ @Inject
private CommandContext commandContext;
@Inject
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index 88f4ba2..b05e4b9 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -122,6 +122,7 @@ import org.apache.isis.core.runtime.persistence.objectstore.transaction.Transact
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindAllInstances;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
import org.apache.isis.core.runtime.runner.opts.OptionHandlerFixtureAbstract;
+import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceInternal;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.adaptermanager.OidAdapterHashMap;
import org.apache.isis.core.runtime.system.persistence.adaptermanager.PojoAdapterHashMap;
@@ -2045,8 +2046,10 @@ public class PersistenceSession implements
public void enlistDeletingAndInvokeIsisRemovingCallbackFacet(final Persistable pojo) {
ObjectAdapter adapter = adapterFor(pojo);
- final IsisTransaction transaction = getCurrentTransaction();
- transaction.enlistDeleting(adapter);
+ final EnlistedObjectsServiceInternal enlistedObjectsServiceInternal =
+ getServicesInjector().lookupService(EnlistedObjectsServiceInternal.class);
+
+ enlistedObjectsServiceInternal.enlistDeleting(adapter);
CallbackFacet.Util.callCallback(adapter, RemovingCallbackFacet.class);
postLifecycleEventIfRequired(adapter, RemovingLifecycleEventFacet.class);
@@ -2237,8 +2240,10 @@ public class PersistenceSession implements
postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
- final IsisTransaction transaction = getCurrentTransaction();
- transaction.enlistCreated(adapter);
+ final EnlistedObjectsServiceInternal enlistedObjectsServiceInternal =
+ getServicesInjector().lookupService(EnlistedObjectsServiceInternal.class);
+
+ enlistedObjectsServiceInternal.enlistCreated(adapter);
} else {
// updating;
@@ -2283,7 +2288,10 @@ public class PersistenceSession implements
postLifecycleEventIfRequired(adapter, UpdatingLifecycleEventFacet.class);
- getCurrentTransaction().enlistUpdating(adapter);
+ final EnlistedObjectsServiceInternal enlistedObjectsServiceInternal =
+ getServicesInjector().lookupService(EnlistedObjectsServiceInternal.class);
+
+ enlistedObjectsServiceInternal.enlistUpdating(adapter);
ensureRootObject(pojo);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ad43cad3/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
index e49601c..54abc1e 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
@@ -20,29 +20,16 @@
package org.apache.isis.core.runtime.system.transaction;
import java.sql.Timestamp;
-import java.util.Collections;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
import java.util.UUID;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.isis.applib.annotation.Bulk;
-import org.apache.isis.applib.annotation.PublishedObject.ChangeKind;
import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
-import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.command.Command2;
import org.apache.isis.applib.services.command.Command3;
@@ -56,18 +43,14 @@ import org.apache.isis.core.commons.components.TransactionScopedComponent;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.util.ToString;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
import org.apache.isis.core.metamodel.services.publishing.PublishingServiceInternal;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.transactions.TransactionState;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
import org.apache.isis.core.runtime.services.auditing.AuditingServiceInternal;
-import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceInternal;
import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
import static org.apache.isis.core.commons.ensure.Ensure.ensureThatState;
@@ -89,17 +72,9 @@ import static org.hamcrest.Matchers.not;
*/
public class IsisTransaction implements TransactionScopedComponent {
-
- public static final Predicate<ObjectAdapter> IS_COMMAND = new Predicate<ObjectAdapter>() {
- @Override
- public boolean apply(ObjectAdapter input) {
- return Command.class.isAssignableFrom(input.getSpecification().getCorrespondingClass());
- }
- };
-
- private static class Placeholder {
- private static Placeholder NEW = new Placeholder("[NEW]");
- private static Placeholder DELETED = new Placeholder("[DELETED]");
+ public static class Placeholder {
+ public static Placeholder NEW = new Placeholder("[NEW]");
+ public static Placeholder DELETED = new Placeholder("[DELETED]");
private final String str;
public Placeholder(String str) {
this.str = str;
@@ -156,7 +131,7 @@ public class IsisTransaction implements TransactionScopedComponent {
public final TransactionState transactionState;
- private State(TransactionState transactionState){
+ State(TransactionState transactionState){
this.transactionState = transactionState;
}
@@ -217,6 +192,7 @@ public class IsisTransaction implements TransactionScopedComponent {
private final InteractionContext interactionContext;
private final PublishingServiceInternal publishingServiceInternal;
private final AuditingServiceInternal auditingServiceInternal;
+ private final EnlistedObjectsServiceInternal enlistedObjectsServiceInternal;
private final UUID transactionId;
@@ -248,6 +224,7 @@ public class IsisTransaction implements TransactionScopedComponent {
this.publishingServiceInternal = lookupService(PublishingServiceInternal.class);
this.auditingServiceInternal = lookupService(AuditingServiceInternal.class);
+ this.enlistedObjectsServiceInternal = lookupService(EnlistedObjectsServiceInternal.class);
this.transactionId = transactionId;
@@ -349,13 +326,6 @@ public class IsisTransaction implements TransactionScopedComponent {
}
/**
- * Maximum number of times we attempt to flush the transaction before giving up.
- */
- private final static int MAX_FLUSH_ATTEMPTS = 10;
-
- /**
- * Mandatory hook method for subclasses to persist all pending changes.
- *
* <p>
* Called by both {@link #commit()} and by {@link #flush()}:
* <table>
@@ -378,7 +348,6 @@ public class IsisTransaction implements TransactionScopedComponent {
*/
private void doFlush() {
- int i = 0;
//
// it's possible that in executing these commands that more will be created.
// so we keep flushing until no more are available (ISIS-533)
@@ -413,17 +382,7 @@ public class IsisTransaction implements TransactionScopedComponent {
}
- private static String asString(Object object) {
- return object != null? object.toString(): null;
- }
-
-
- protected AuthenticationSession getAuthenticationSession() {
- return IsisContext.getAuthenticationSession();
- }
-
-
// ////////////////////////////////////////////////////////////////
// preCommit, commit
// ////////////////////////////////////////////////////////////////
@@ -444,45 +403,24 @@ public class IsisTransaction implements TransactionScopedComponent {
}
try {
- final Map<AdapterAndProperty, PreAndPostValues> processedObjectProperties = Maps.newLinkedHashMap();
- while(!changedObjectProperties.isEmpty()) {
+ // ensureCommandsPersistedIfDirtyXactn
+ final Command command = commandContext.getCommand();
- final Set<AdapterAndProperty> keys = Sets.newLinkedHashSet(changedObjectProperties.keySet());
- for (final AdapterAndProperty aap : keys) {
-
- final PreAndPostValues papv = changedObjectProperties.remove(aap);
-
- final ObjectAdapter adapter = aap.getAdapter();
- if(adapter.isDestroyed()) {
- // don't touch the object!!!
- // JDO, for example, will complain otherwise...
- papv.setPost(Placeholder.DELETED);
- } else {
- papv.setPost(aap.getPropertyValue());
- }
-
- // if we encounter the same objectProperty again, this will simply overwrite it
- processedObjectProperties.put(aap, papv);
- }
+ // ensure that any changed objects means that the command should be persisted
+ final boolean hasChangedAdapters = enlistedObjectsServiceInternal.hasChangedAdapters();
+ if(hasChangedAdapters && command.getMemberIdentifier() != null) {
+ command.setPersistHint(true);
}
- final Set<Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties =
- Collections.unmodifiableSet(
- Sets.filter(processedObjectProperties.entrySet(), PreAndPostValues.Predicates.CHANGED));
-
- ensureCommandsPersistedIfDirtyXactn(changedObjectProperties);
-
- try {
- auditingServiceInternal.audit(changedObjectProperties);
- } finally {
- // not needed in production, but is required for integration testing
- this.changedObjectProperties.clear();
- }
+ auditingServiceInternal.audit();
- publishingServiceInternal.publishObjects(this.changeKindByEnlistedAdapter);
+ publishingServiceInternal.publishObjects();
doFlush();
- closeOtherApplibServicesIfConfigured();
+ final ActionInvocationContext actionInvocationContext = lookupService(ActionInvocationContext.class);
+ if(actionInvocationContext != null) {
+ Bulk.InteractionContext.current.set(null);
+ }
completeCommandAndInteractionAndClearDomainEvents();
doFlush();
@@ -495,36 +433,6 @@ public class IsisTransaction implements TransactionScopedComponent {
}
}
- private void ensureCommandsPersistedIfDirtyXactn(
- final Set<Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties) {
-
- final Command command = commandContext.getCommand();
-
- // ensure that any changed objects means that the command should be persisted
- final Set<ObjectAdapter> changedAdapters = findChangedAdapters(changedObjectProperties);
- if(!changedAdapters.isEmpty() && command.getMemberIdentifier() != null) {
- command.setPersistHint(true);
- }
- }
-
-
- private static Set<ObjectAdapter> findChangedAdapters(
- final Set<Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties) {
- return Sets.newHashSet(
- Iterables.filter(
- Iterables.transform(
- changedObjectProperties,
- AdapterAndProperty.Functions.GET_ADAPTER),
- Predicates.not(IS_COMMAND)));
- }
-
- private void closeOtherApplibServicesIfConfigured() {
- final ActionInvocationContext actionInvocationContext = lookupService(ActionInvocationContext.class);
- if(actionInvocationContext != null) {
- Bulk.InteractionContext.current.set(null);
- }
- }
-
private void completeCommandAndInteractionAndClearDomainEvents() {
final Command command = commandContext.getCommand();
@@ -679,15 +587,6 @@ public class IsisTransaction implements TransactionScopedComponent {
// Depenendencies (from constructor)
// ////////////////////////////////////////////////////////////////
- /**
- * The owning {@link IsisTransactionManager transaction manager}.
- *
- * <p>
- * Injected in constructor
- */
- public IsisTransactionManager getTransactionManager() {
- return transactionManager;
- }
/**
* The {@link org.apache.isis.core.commons.authentication.MessageBroker} for this transaction.
@@ -701,302 +600,6 @@ public class IsisTransaction implements TransactionScopedComponent {
return messageBroker;
}
- public static class AdapterAndProperty {
-
- private final ObjectAdapter objectAdapter;
- private final ObjectAssociation property;
- private final Bookmark bookmark;
- private final String propertyId;
- private final String bookmarkStr;
-
- public static AdapterAndProperty of(ObjectAdapter adapter, ObjectAssociation property) {
- return new AdapterAndProperty(adapter, property);
- }
-
- private AdapterAndProperty(ObjectAdapter adapter, ObjectAssociation property) {
- this.objectAdapter = adapter;
- this.property = property;
-
- final RootOid oid = (RootOid) adapter.getOid();
-
- final String objectType = oid.getObjectSpecId().asString();
- final String identifier = oid.getIdentifier();
- bookmark = new Bookmark(objectType, identifier);
- bookmarkStr = bookmark.toString();
-
- propertyId = property.getId();
- }
-
- public ObjectAdapter getAdapter() {
- return objectAdapter;
- }
- public ObjectAssociation getProperty() {
- return property;
- }
-
- public Bookmark getBookmark() {
- return bookmark;
- }
- public String getPropertyId() {
- return propertyId;
- }
-
- public String getMemberId() {
- return property.getIdentifier().toClassAndNameIdentityString();
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final AdapterAndProperty that = (AdapterAndProperty) o;
-
- if (bookmarkStr != null ? !bookmarkStr.equals(that.bookmarkStr) : that.bookmarkStr != null) return false;
- if (propertyId != null ? !propertyId.equals(that.propertyId) : that.propertyId != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = propertyId != null ? propertyId.hashCode() : 0;
- result = 31 * result + (bookmarkStr != null ? bookmarkStr.hashCode() : 0);
- return result;
- }
-
- @Override
- public String toString() {
- return bookmarkStr + " , " + getProperty().getId();
- }
-
-
- private Object getPropertyValue() {
- ObjectAdapter referencedAdapter = property.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK);
- return referencedAdapter == null ? null : referencedAdapter.getObject();
- }
-
- static class Functions {
- private Functions(){}
-
- static final Function<Entry<AdapterAndProperty, PreAndPostValues>, ObjectAdapter> GET_ADAPTER = new Function<Entry<AdapterAndProperty, PreAndPostValues>, ObjectAdapter>() {
- @Override
- public ObjectAdapter apply(Entry<AdapterAndProperty, PreAndPostValues> input) {
- final AdapterAndProperty aap = input.getKey();
- return aap.getAdapter();
- }
- };
-
- }
-
- }
-
-
- ////////////////////////////////////////////////////////////////////////
- // Auditing/Publishing object tracking
- ////////////////////////////////////////////////////////////////////////
-
- public static class PreAndPostValues {
-
- static class Predicates {
- final static Predicate<Entry<?, PreAndPostValues>> CHANGED = new Predicate<Entry<?, PreAndPostValues>>(){
- @Override
- public boolean apply(Entry<?, PreAndPostValues> input) {
- final PreAndPostValues papv = input.getValue();
- return papv.differ();
- }};
- }
-
- private final Object pre;
- /**
- * Eagerly calculated because it could be that the object referenced ends up being deleted by the time that the xactn completes.
- */
- private final String preString;
-
- /**
- * Updated in {@link #setPost(Object)}
- */
- private Object post;
- /**
- * Updated in {@link #setPost(Object)}, along with {@link #post}.
- */
- private String postString;
-
-
- public static PreAndPostValues pre(Object preValue) {
- return new PreAndPostValues(preValue, null);
- }
-
- private PreAndPostValues(Object pre, Object post) {
- this.pre = pre;
- this.post = post;
- this.preString = asString(pre);
- }
- /**
- * The object that was referenced before this object was changed
- *
- * <p>
- * Note that this referenced object itself could end up being deleted in the course of the transaction; in which case use
- * {@link #getPreString()} which is the eagerly cached <tt>toString</tt> of said object.
- */
- public Object getPre() {
- return pre;
- }
- public String getPreString() {
- return preString;
- }
- public Object getPost() {
- return post;
- }
- public String getPostString() {
- return postString;
- }
- public void setPost(Object post) {
- this.post = post;
- this.postString = asString(post);
- }
-
- @Override
- public String toString() {
- return getPre() + " -> " + getPost();
- }
-
- public boolean differ() {
- if(getPre() == Placeholder.NEW || getPost() == Placeholder.DELETED) {
- return true;
- }
- return !Objects.equal(getPre(), getPost());
- }
- }
-
-
- private final Map<ObjectAdapter,ChangeKind> changeKindByEnlistedAdapter = Maps.newLinkedHashMap();
- private final Map<AdapterAndProperty, PreAndPostValues> changedObjectProperties = Maps.newLinkedHashMap();
-
-
-
-
- /**
- * Auditing and publishing support: for object stores to enlist an object that has just been created,
- * capturing a dummy value <tt>'[NEW]'</tt> for the pre-modification value.
- *
- * <p>
- * The post-modification values are captured in {@link #preCommit()}.
- *
- * <p>
- * Supported by the JDO object store; check documentation for support in other objectstores.
- */
- public void enlistCreated(ObjectAdapter adapter) {
- enlist(adapter, ChangeKind.CREATE);
- for (ObjectAssociation property : adapter.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES)) {
- final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
- if(property.isNotPersisted()) {
- continue;
- }
- if(changedObjectProperties.containsKey(aap)) {
- // already enlisted, so ignore
- return;
- }
- PreAndPostValues papv = PreAndPostValues.pre(Placeholder.NEW);
- changedObjectProperties.put(aap, papv);
- }
- }
-
- /**
- * Auditing and publishing support: for object stores to enlist an object that is about to be updated,
- * capturing the pre-modification values of the properties of the {@link ObjectAdapter}.
- *
- * <p>
- * The post-modification values are captured in {@link #preCommit()}.
- *
- * <p>
- * Supported by the JDO object store; check documentation for support in other objectstores.
- */
- public void enlistUpdating(ObjectAdapter adapter) {
- enlist(adapter, ChangeKind.UPDATE);
- for (ObjectAssociation property : adapter.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES)) {
- final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
- if(property.isNotPersisted()) {
- continue;
- }
- if(changedObjectProperties.containsKey(aap)) {
- // already enlisted, so ignore
- return;
- }
- PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
- changedObjectProperties.put(aap, papv);
- }
- }
-
- /**
- * Auditing and publishing support: for object stores to enlist an object that is about to be deleted,
- * capturing the pre-deletion value of the properties of the {@link ObjectAdapter}.
- *
- * <p>
- * The post-modification values are captured in {@link #preCommit()}. In the case of deleted objects, a
- * dummy value <tt>'[DELETED]'</tt> is used as the post-modification value.
- *
- * <p>
- * Supported by the JDO object store; check documentation for support in other objectstores.
- */
- public void enlistDeleting(ObjectAdapter adapter) {
- final boolean enlisted = enlist(adapter, ChangeKind.DELETE);
- if(!enlisted) {
- return;
- }
- for (ObjectAssociation property : adapter.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.PROPERTIES)) {
- final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
- if(property.isNotPersisted()) {
- continue;
- }
- if(changedObjectProperties.containsKey(aap)) {
- // already enlisted, so ignore
- return;
- }
- PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
- changedObjectProperties.put(aap, papv);
- }
- }
-
-
- /**
- *
- * @param adapter
- * @param current
- * @return <code>true</code> if successfully enlisted, <code>false</code> if was already enlisted
- */
- private boolean enlist(final ObjectAdapter adapter, final ChangeKind current) {
- final ChangeKind previous = changeKindByEnlistedAdapter.get(adapter);
- if(previous == null) {
- changeKindByEnlistedAdapter.put(adapter, current);
- return true;
- }
- switch (previous) {
- case CREATE:
- switch (current) {
- case DELETE:
- changeKindByEnlistedAdapter.remove(adapter);
- case CREATE:
- case UPDATE:
- return false;
- }
- break;
- case UPDATE:
- switch (current) {
- case DELETE:
- changeKindByEnlistedAdapter.put(adapter, current);
- return true;
- case CREATE:
- case UPDATE:
- return false;
- }
- break;
- case DELETE:
- return false;
- }
- return previous == null;
- }
-
////////////////////////////////////////////////////////////////////////
// Dependencies (lookup)
@@ -1013,6 +616,4 @@ public class IsisTransaction implements TransactionScopedComponent {
private <T> T lookupServiceIfAny(final Class<T> serviceType) {
return servicesInjector.lookupService(serviceType);
}
-
-
}
[2/3] isis git commit: ISIS-1370: moved AuditingServiceInternal to an
auditing package.
Posted by da...@apache.org.
ISIS-1370: moved AuditingServiceInternal to an auditing package.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/e2fb62e6
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/e2fb62e6
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/e2fb62e6
Branch: refs/heads/ISIS-1291
Commit: e2fb62e65eebd8f9930947333d72cb73144fdce2
Parents: 5870f6a
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun May 1 11:33:51 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun May 1 11:33:51 2016 +0100
----------------------------------------------------------------------
.../auditing/AuditingServiceInternal.java | 117 +++++++++++++++++++
.../publishing/AuditingServiceInternal.java | 117 -------------------
.../system/transaction/IsisTransaction.java | 2 +-
.../handlers/DomainObjectInvocationHandler.java | 8 +-
4 files changed, 122 insertions(+), 122 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/e2fb62e6/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
new file mode 100644
index 0000000..a470946
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/auditing/AuditingServiceInternal.java
@@ -0,0 +1,117 @@
+/*
+ * 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.core.runtime.services.auditing;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.audit.AuditingService3;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.clock.ClockService;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.user.UserService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
+import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+
+/**
+ * Wrapper around {@link org.apache.isis.applib.services.audit.AuditingService3}. Is a no-op if there is no injected service.
+ */
+@DomainService(nature = NatureOfService.DOMAIN)
+public class AuditingServiceInternal {
+
+
+ @Programmatic
+ public boolean canAudit() {
+ return auditingServiceIfAny != null;
+ }
+
+ @Programmatic
+ public void audit(
+ final Set<Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues>> changedObjectProperties) {
+
+ if(!canAudit()) {
+ return;
+ }
+
+ final String currentUser = userService.getUser().getName();
+ final java.sql.Timestamp currentTime = clockService.nowAsJavaSqlTimestamp();
+
+ for (Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry : changedObjectProperties) {
+ auditChangedProperty(currentTime, currentUser, auditEntry);
+ }
+
+ }
+
+ private void auditChangedProperty(
+ final java.sql.Timestamp timestamp,
+ final String user,
+ final Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry) {
+
+ final IsisTransaction.AdapterAndProperty aap = auditEntry.getKey();
+ final ObjectAdapter adapter = aap.getAdapter();
+
+ final AuditableFacet auditableFacet = adapter.getSpecification().getFacet(AuditableFacet.class);
+ if(auditableFacet == null || auditableFacet.isDisabled()) {
+ return;
+ }
+
+ final Bookmark target = aap.getBookmark();
+ final String propertyId = aap.getPropertyId();
+ final String memberId = aap.getMemberId();
+
+ final IsisTransaction.PreAndPostValues papv = auditEntry.getValue();
+ final String preValue = papv.getPreString();
+ final String postValue = papv.getPostString();
+
+
+ final String targetClass = CommandUtil.targetClassNameFor(adapter);
+
+ final Command command = commandContext.getCommand();
+ final UUID transactionId = command.getTransactionId();
+
+ auditingServiceIfAny
+ .audit(transactionId, targetClass, target, memberId, propertyId, preValue, postValue, user, timestamp);
+ }
+
+ /**
+ * could be null if none has been registered.
+ */
+ @Inject
+ private AuditingService3 auditingServiceIfAny;
+
+ @Inject
+ UserService userService;
+
+ @Inject
+ ClockService clockService;
+
+ @Inject
+ CommandContext commandContext;
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e2fb62e6/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java
deleted file mode 100644
index 3f29804..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/AuditingServiceInternal.java
+++ /dev/null
@@ -1,117 +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.core.runtime.services.publishing;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import javax.inject.Inject;
-
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.audit.AuditingService3;
-import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.clock.ClockService;
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.CommandContext;
-import org.apache.isis.applib.services.user.UserService;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
-import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
-import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
-
-/**
- * Wrapper around {@link org.apache.isis.applib.services.audit.AuditingService3}. Is a no-op if there is no injected service.
- */
-@DomainService(nature = NatureOfService.DOMAIN)
-public class AuditingServiceInternal {
-
-
- @Programmatic
- public boolean canAudit() {
- return auditingServiceIfAny != null;
- }
-
- @Programmatic
- public void audit(
- final Set<Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues>> changedObjectProperties) {
-
- if(!canAudit()) {
- return;
- }
-
- final String currentUser = userService.getUser().getName();
- final java.sql.Timestamp currentTime = clockService.nowAsJavaSqlTimestamp();
-
- for (Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry : changedObjectProperties) {
- auditChangedProperty(currentTime, currentUser, auditEntry);
- }
-
- }
-
- private void auditChangedProperty(
- final java.sql.Timestamp timestamp,
- final String user,
- final Map.Entry<IsisTransaction.AdapterAndProperty, IsisTransaction.PreAndPostValues> auditEntry) {
-
- final IsisTransaction.AdapterAndProperty aap = auditEntry.getKey();
- final ObjectAdapter adapter = aap.getAdapter();
-
- final AuditableFacet auditableFacet = adapter.getSpecification().getFacet(AuditableFacet.class);
- if(auditableFacet == null || auditableFacet.isDisabled()) {
- return;
- }
-
- final Bookmark target = aap.getBookmark();
- final String propertyId = aap.getPropertyId();
- final String memberId = aap.getMemberId();
-
- final IsisTransaction.PreAndPostValues papv = auditEntry.getValue();
- final String preValue = papv.getPreString();
- final String postValue = papv.getPostString();
-
-
- final String targetClass = CommandUtil.targetClassNameFor(adapter);
-
- final Command command = commandContext.getCommand();
- final UUID transactionId = command.getTransactionId();
-
- auditingServiceIfAny
- .audit(transactionId, targetClass, target, memberId, propertyId, preValue, postValue, user, timestamp);
- }
-
- /**
- * could be null if none has been registered.
- */
- @Inject
- private AuditingService3 auditingServiceIfAny;
-
- @Inject
- UserService userService;
-
- @Inject
- ClockService clockService;
-
- @Inject
- CommandContext commandContext;
-
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/e2fb62e6/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
index 99b3079..e49601c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
@@ -66,7 +66,7 @@ import org.apache.isis.core.metamodel.transactions.TransactionState;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
-import org.apache.isis.core.runtime.services.publishing.AuditingServiceInternal;
+import org.apache.isis.core.runtime.services.auditing.AuditingServiceInternal;
import org.apache.isis.core.runtime.system.context.IsisContext;
import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
http://git-wip-us.apache.org/repos/asf/isis/blob/e2fb62e6/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
index 023921c..18a3f26 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -766,11 +766,11 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
}
private ObjectSpecificationDefault getJavaSpecification(final Class<?> clazz) {
- final ObjectSpecification nos = getSpecification(clazz);
- if (!(nos instanceof ObjectSpecificationDefault)) {
- throw new UnsupportedOperationException("Only Java is supported (specification is '" + nos.getClass().getCanonicalName() + "')");
+ final ObjectSpecification objectSpec = getSpecification(clazz);
+ if (!(objectSpec instanceof ObjectSpecificationDefault)) {
+ throw new UnsupportedOperationException("Only Java is supported (specification is '" + objectSpec.getClass().getCanonicalName() + "')");
}
- return (ObjectSpecificationDefault) nos;
+ return (ObjectSpecificationDefault) objectSpec;
}
private ObjectSpecification getSpecification(final Class<?> type) {