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/12 14:52:10 UTC
[1/2] isis git commit: ISIS-1370: refining the API for
PublisherService.
Repository: isis
Updated Branches:
refs/heads/ISIS-1291 2a8918287 -> b8d19e67d
ISIS-1370: refining the API for PublisherService.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/ea7c1904
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/ea7c1904
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/ea7c1904
Branch: refs/heads/ISIS-1291
Commit: ea7c1904429e327647def9a3f5cd7d95a804c9ab
Parents: 2a89182
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu May 12 15:50:43 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu May 12 15:50:43 2016 +0100
----------------------------------------------------------------------
.../applib/services/changes/ChangedObjects.java | 38 --
.../isis/applib/services/iactn/Interaction.java | 36 +-
.../services/publish/PublishedObjects.java | 47 +++
.../services/publish/PublisherService.java | 3 +-
.../publish/PublisherServiceLogging.java | 5 +-
.../applib/service/DomainChangeJdoAbstract.java | 19 +-
...onInvocationFacetForDomainEventAbstract.java | 6 +-
.../publishedobject/PublishedObjectFacet.java | 17 +
...etterOrClearFacetForDomainEventAbstract.java | 6 +-
.../services/changes/ChangedObjectsDefault.java | 178 ---------
.../changes/ChangedObjectsServiceInternal.java | 13 +-
.../publish/PublishedObjectsDefault.java | 216 ++++++++++
.../PublishingServiceInternalDefault.java | 397 +++++++++++++++++++
.../PublishingServiceInternalDefault.java | 394 ------------------
14 files changed, 741 insertions(+), 634 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/applib/src/main/java/org/apache/isis/applib/services/changes/ChangedObjects.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/changes/ChangedObjects.java b/core/applib/src/main/java/org/apache/isis/applib/services/changes/ChangedObjects.java
deleted file mode 100644
index 6a194a2..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/changes/ChangedObjects.java
+++ /dev/null
@@ -1,38 +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.applib.services.changes;
-
-import java.sql.Timestamp;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.HasTransactionId;
-import org.apache.isis.applib.services.HasUsername;
-import org.apache.isis.schema.chg.v1.ChangesDto;
-
-public interface ChangedObjects extends HasTransactionId, HasUsername {
-
- @Programmatic
- Timestamp getCompletedAt();
-
- @Programmatic
- String getUser();
-
- @Programmatic
- ChangesDto getDto();
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java b/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
index 584bbb1..9281bae 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
@@ -316,6 +316,8 @@ public class Interaction implements HasTransactionId {
private final String memberIdentifier;
private final Object target;
+ private final String targetMember;
+ private final String targetClass;
private final Interaction interaction;
private final InteractionType interactionType;
@@ -323,15 +325,19 @@ public class Interaction implements HasTransactionId {
final Interaction interaction,
final InteractionType interactionType,
final String memberIdentifier,
- final Object target) {
+ final Object target,
+ final String targetMember,
+ final String targetClass) {
this.interaction = interaction;
this.interactionType = interactionType;
this.memberIdentifier = memberIdentifier;
this.target = target;
+ this.targetMember = targetMember;
+ this.targetClass = targetClass;
}
//endregion
- //region > via constructor: interaction, interactionType, memberId, target
+ //region > via constructor: interaction, interactionType, memberId, target, targetMember, targetClass
public Interaction getInteraction() {
return interaction;
@@ -349,6 +355,20 @@ public class Interaction implements HasTransactionId {
return target;
}
+ /**
+ * A human-friendly description of the class of the target object.
+ */
+ public String getTargetClass() {
+ return targetClass;
+ }
+
+ /**
+ * The human-friendly name of the action invoked/property edited on the target object.
+ */
+ public String getTargetMember() {
+ return targetMember;
+ }
+
//endregion
//region > parent, children
@@ -609,8 +629,10 @@ public class Interaction implements HasTransactionId {
final Interaction interaction,
final String memberId,
final Object target,
- final List<Object> args) {
- super(interaction, InteractionType.ACTION_INVOCATION, memberId, target);
+ final List<Object> args,
+ final String targetMember,
+ final String targetClass) {
+ super(interaction, InteractionType.ACTION_INVOCATION, memberId, target, targetMember, targetClass);
this.args = args;
}
@@ -627,8 +649,10 @@ public class Interaction implements HasTransactionId {
final Interaction interaction,
final String memberId,
final Object target,
- final Object newValue) {
- super(interaction, InteractionType.PROPERTY_EDIT, memberId, target);
+ final Object newValue,
+ final String targetMember,
+ final String targetClass) {
+ super(interaction, InteractionType.PROPERTY_EDIT, memberId, target, targetMember, targetClass);
this.newValue = newValue;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishedObjects.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishedObjects.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishedObjects.java
new file mode 100644
index 0000000..35a1f6f
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishedObjects.java
@@ -0,0 +1,47 @@
+/*
+ * 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.applib.services.publish;
+
+import java.sql.Timestamp;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.HasTransactionId;
+import org.apache.isis.applib.services.HasUsername;
+import org.apache.isis.schema.chg.v1.ChangesDto;
+
+public interface PublishedObjects extends HasTransactionId, HasUsername {
+
+ @Programmatic
+ Timestamp getCompletedAt();
+
+ @Programmatic
+ String getUser();
+
+ @Programmatic
+ ChangesDto getDto();
+
+ @Programmatic
+ int numberCreated();
+
+ @Programmatic
+ int numberUpdated();
+
+ @Programmatic
+ int numberDeleted();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
index d1b4ff9..9c1d7ca 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
@@ -20,7 +20,6 @@ package org.apache.isis.applib.services.publish;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.services.iactn.Interaction;
-import org.apache.isis.applib.services.changes.ChangedObjects;
/**
* Replaces {@link PublishingService}.
@@ -40,7 +39,7 @@ public interface PublisherService {
void publish(final Interaction.Execution<?, ?> execution);
@Programmatic
- void publish(final ChangedObjects changedObjects);
+ void publish(final PublishedObjects publishedObjects);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
index d3bf438..b928d37 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
@@ -27,7 +27,6 @@ import org.slf4j.LoggerFactory;
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.services.command.CommandContext;
-import org.apache.isis.applib.services.changes.ChangedObjects;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.user.UserService;
import org.apache.isis.schema.chg.v1.ChangesDto;
@@ -60,13 +59,13 @@ public class PublisherServiceLogging implements PublisherService {
}
@Override
- public void publish(final ChangedObjects changedObjects) {
+ public void publish(final PublishedObjects publishedObjects) {
if(!LOG.isDebugEnabled()) {
return;
}
- final ChangesDto changesDto = changedObjects.getDto();
+ final ChangesDto changesDto = publishedObjects.getDto();
LOG.debug(ChangesDtoUtils.toXml(changesDto));
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/DomainChangeJdoAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/DomainChangeJdoAbstract.java b/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/DomainChangeJdoAbstract.java
index 6dfa7da..5c8f74a 100644
--- a/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/DomainChangeJdoAbstract.java
+++ b/core/applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/DomainChangeJdoAbstract.java
@@ -181,20 +181,29 @@ public abstract class DomainChangeJdoAbstract {
private String targetAction;
/**
- * The action invoked which caused the domain object to be changed..
- *
+ * The member interaction (ie action invocation or property edit) which caused the domain object to be changed.
+ *
* <p>
- * Populated only for <tt>CommandJdo</tt>s.
- *
+ * Populated for commands and for published events that represent action invocations or property edits.
+ * </p>
+ *
* <p>
* This dummy implementation is a trick so that Isis will render the property in a standalone table. Each of the
* subclasses override with the "real" implementation.
+ * </p>
+ *
+ * <p>
+ * NB: commands and published events applied only to actions, hence the name of this field. In a future release
+ * the name of this field may change to "TargetMember". Note that the {@link PropertyLayout} already uses
+ * "Member" this as a name hint.
+ * </p>
+ *
*/
@Property(
optionality = OPTIONAL
)
@PropertyLayout(
- named="Action",
+ named="Member",
hidden = Where.ALL_EXCEPT_STANDALONE_TABLES
)
@MemberOrder(name="Target", sequence = "20")
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index c900f17..1222033 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -196,8 +196,12 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
final List<ObjectAdapter> argumentAdapterList = Arrays.asList(argumentAdapters);
final List<Object> argumentPojos = ObjectAdapter.Util.unwrap(argumentAdapterList);
+ final String targetMember = CommandUtil.targetMemberNameFor(owningAction);
+ final String targetClass = CommandUtil.targetClassNameFor(targetAdapter);
+
final Interaction.ActionInvocation execution =
- new Interaction.ActionInvocation(interaction, actionId, targetPojo, argumentPojos);
+ new Interaction.ActionInvocation(interaction, actionId, targetPojo, argumentPojos, targetMember,
+ targetClass);
final Interaction.MemberExecutor<Interaction.ActionInvocation> callable =
new Interaction.MemberExecutor<Interaction.ActionInvocation>() {
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publishedobject/PublishedObjectFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publishedobject/PublishedObjectFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publishedobject/PublishedObjectFacet.java
index e7736bb..f344c00 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publishedobject/PublishedObjectFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publishedobject/PublishedObjectFacet.java
@@ -19,7 +19,10 @@
package org.apache.isis.core.metamodel.facets.object.publishedobject;
+import com.google.common.base.Predicate;
+
import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.facets.SingleValueFacet;
/**
@@ -28,4 +31,18 @@ import org.apache.isis.core.metamodel.facets.SingleValueFacet;
*/
public interface PublishedObjectFacet extends SingleValueFacet<PublishedObject.PayloadFactory> {
+ class Predicates {
+ private Predicates(){}
+
+ public static Predicate<ObjectAdapter> isPublished() {
+ return new Predicate<ObjectAdapter>() {
+ @Override
+ public boolean apply(final ObjectAdapter objectAdapter) {
+ final PublishedObjectFacet publishedObjectFacet =
+ objectAdapter.getSpecification().getFacet(PublishedObjectFacet.class);
+ return publishedObjectFacet != null;
+ }
+ };
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
index c4899f8..e7af2d6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
@@ -38,6 +38,7 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facets.DomainEventHelper;
import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
import org.apache.isis.core.metamodel.facets.properties.publish.PublishedPropertyFacet;
import org.apache.isis.core.metamodel.facets.properties.update.clear.PropertyClearFacet;
@@ -188,8 +189,11 @@ public abstract class PropertySetterOrClearFacetForDomainEventAbstract
final Object target = ObjectAdapter.Util.unwrap(targetAdapter);
final Object argValue = ObjectAdapter.Util.unwrap(newValueAdapter);
+ final String targetMember = CommandUtil.targetMemberNameFor(owningProperty);
+ final String targetClass = CommandUtil.targetClassNameFor(targetAdapter);
+
final Interaction.PropertyEdit execution =
- new Interaction.PropertyEdit(interaction, propertyId, target, argValue);
+ new Interaction.PropertyEdit(interaction, propertyId, target, argValue, targetMember, targetClass);
final Interaction.MemberExecutor<Interaction.PropertyEdit> executor =
new Interaction.MemberExecutor<Interaction.PropertyEdit>() {
@Override
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsDefault.java
deleted file mode 100644
index f2d203a..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsDefault.java
+++ /dev/null
@@ -1,178 +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.changes;
-
-import java.sql.Timestamp;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.PublishedObject;
-import org.apache.isis.applib.services.changes.ChangedObjects;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
-import org.apache.isis.core.metamodel.facets.object.publishedobject.PublishedObjectFacet;
-import org.apache.isis.schema.chg.v1.ChangesDto;
-import org.apache.isis.schema.chg.v1.ObjectsDto;
-import org.apache.isis.schema.common.v1.OidDto;
-import org.apache.isis.schema.common.v1.OidsDto;
-import org.apache.isis.schema.utils.jaxbadapters.JavaSqlTimestampXmlGregorianCalendarAdapter;
-
-/**
- * Captures which objects were created, updated or deleted in the course of a transaction.
- */
-public class ChangedObjectsDefault implements ChangedObjects {
-
- private UUID transactionUuid;
- private final String userName;
- private final Timestamp completedAt;
- private final Map<ObjectAdapter, PublishedObject.ChangeKind> changesByAdapter;
-
- public ChangedObjectsDefault(
- final UUID transactionUuid,
- final String userName,
- final Timestamp completedAt,
- final Map<ObjectAdapter, PublishedObject.ChangeKind> changesByAdapter) {
- this.transactionUuid = transactionUuid;
- this.userName = userName;
- this.completedAt = completedAt;
- this.changesByAdapter = changesByAdapter;
- }
-
- //region > transactionId, completedAt, user
- @Programmatic
- @Override
- public UUID getTransactionId() {
- return transactionUuid;
- }
-
- /**
- * Unused; the {@link #getTransactionId()} is set in the constructor.
- */
- @Override
- public void setTransactionId(final UUID transactionId) {
- this.transactionUuid = transactionId;
- }
-
- /**
- * The date/time at which this set of enlisted objects was created (approx the completion time of the transaction).
- */
- @Override
- public Timestamp getCompletedAt() {
- return completedAt;
- }
-
- @Override
- public String getUser() {
- return userName;
- }
-
- @Programmatic
- @Override
- public String getUsername() {
- return getUser();
- }
- //endregion
-
- private ChangesDto dto;
-
- @Override
- public ChangesDto getDto() {
- return dto != null ? dto : (dto = newDto());
- }
-
-
- //region > newDto, newObjectsDto, newChangesDto
-
- private ChangesDto newDto() {
- final ObjectsDto objectsDto = newObjectsDto(changesByAdapter);
- return newChangesDto(objectsDto, transactionUuid, userName, completedAt);
- }
-
- protected ObjectsDto newObjectsDto(
- final Map<ObjectAdapter, PublishedObject.ChangeKind> changeKindByEnlistedAdapter) {
- final ObjectsDto objectsDto = new ObjectsDto();
-
- final OidsDto createdOids = new OidsDto();
- final OidsDto updatedOids = new OidsDto();
- final OidsDto deletedOids = new OidsDto();
-
- for (final Map.Entry<ObjectAdapter, PublishedObject.ChangeKind> adapterAndChange : changeKindByEnlistedAdapter.entrySet()) {
- final ObjectAdapter enlistedAdapter = adapterAndChange.getKey();
-
- final PublishedObjectFacet publishedObjectFacet =
- enlistedAdapter.getSpecification().getFacet(PublishedObjectFacet.class);
-
- if(publishedObjectFacet == null) {
- continue;
- }
-
- final RootOid rootOid = (RootOid) enlistedAdapter.getOid();
- final OidDto oidDto = rootOid.asOidDto();
-
- final PublishedObject.ChangeKind changeKind = adapterAndChange.getValue();
- switch (changeKind) {
- case CREATE:
- createdOids.getOid().add(oidDto);
- break;
- case UPDATE:
- updatedOids.getOid().add(oidDto);
- break;
- case DELETE:
- deletedOids.getOid().add(oidDto);
- break;
- default:
- // shouldn't happen
- throw new RuntimeException("ChangeKind '" + changeKind + "' not recognized");
- }
- }
-
- objectsDto.setCreated(createdOids);
- objectsDto.setUpdated(updatedOids);
- objectsDto.setDeleted(deletedOids);
- return objectsDto;
- }
-
- protected ChangesDto newChangesDto(
- final ObjectsDto objectsDto,
- final UUID transactionUuid,
- final String userName,
- final Timestamp timestamp) {
- final String transactionId = transactionUuid.toString();
- final ChangesDto changesDto = new ChangesDto();
-
- changesDto.setMajorVersion("1");
- changesDto.setMinorVersion("0");
-
- changesDto.setTransactionId(transactionId);
- changesDto.setUser(userName);
- changesDto.setCompletedAt(
- JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
- changesDto.setObjects(objectsDto);
- return changesDto;
- }
-
-
-
- //endregion
-
-
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java
index d907c0a..9981059 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java
@@ -246,18 +246,19 @@ public class ChangedObjectsServiceInternal {
return changeKindByEnlistedAdapter;
}
-
- static String asString(Object object) {
- return object != null? object.toString(): null;
- }
-
@Programmatic
public int numberObjectsDirtied() {
- return changedObjectProperties.size();
+ return changeKindByEnlistedAdapter.size();
}
@Programmatic
public int numberObjectPropertiesModified() {
return changedObjectProperties.size();
}
+
+
+ static String asString(Object object) {
+ return object != null? object.toString(): null;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishedObjectsDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishedObjectsDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishedObjectsDefault.java
new file mode 100644
index 0000000..da24a80
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishedObjectsDefault.java
@@ -0,0 +1,216 @@
+/*
+ * 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.publish;
+
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimaps;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.applib.services.publish.PublishedObjects;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.schema.chg.v1.ChangesDto;
+import org.apache.isis.schema.chg.v1.ObjectsDto;
+import org.apache.isis.schema.common.v1.OidDto;
+import org.apache.isis.schema.common.v1.OidsDto;
+import org.apache.isis.schema.utils.jaxbadapters.JavaSqlTimestampXmlGregorianCalendarAdapter;
+
+/**
+ * Captures which objects were created, updated or deleted in the course of a transaction.
+ */
+public class PublishedObjectsDefault implements PublishedObjects {
+
+ //region > constructor, fields
+ private UUID transactionUuid;
+ private final String userName;
+ private final Timestamp completedAt;
+ private final Map<ObjectAdapter, PublishedObject.ChangeKind> changesByAdapter;
+
+ public PublishedObjectsDefault(
+ final UUID transactionUuid,
+ final String userName,
+ final Timestamp completedAt,
+ final Map<ObjectAdapter, PublishedObject.ChangeKind> changesByAdapter) {
+ this.transactionUuid = transactionUuid;
+ this.userName = userName;
+ this.completedAt = completedAt;
+ this.changesByAdapter = changesByAdapter;
+ }
+ //endregion
+
+
+ //region > transactionId, completedAt, user
+ @Programmatic
+ @Override
+ public UUID getTransactionId() {
+ return transactionUuid;
+ }
+
+ /**
+ * Unused; the {@link #getTransactionId()} is set in the constructor.
+ */
+ @Override
+ public void setTransactionId(final UUID transactionId) {
+ this.transactionUuid = transactionId;
+ }
+
+ /**
+ * The date/time at which this set of enlisted objects was created (approx the completion time of the transaction).
+ */
+ @Override
+ public Timestamp getCompletedAt() {
+ return completedAt;
+ }
+
+ @Override
+ public String getUser() {
+ return userName;
+ }
+
+ @Programmatic
+ @Override
+ public String getUsername() {
+ return getUser();
+ }
+ //endregion
+
+ //region > dto
+ /**
+ * lazily computed
+ */
+ private ChangesDto dto;
+
+ @Override
+ public ChangesDto getDto() {
+ return dto != null ? dto : (dto = newDto());
+ }
+ //endregion
+
+ //region > numberCreated, numberUpdated, numberDeleted
+
+ @Override
+ public int numberCreated() {
+ return numAdaptersOfKind(PublishedObject.ChangeKind.CREATE);
+ }
+
+ @Override
+ public int numberUpdated() {
+ return numAdaptersOfKind(PublishedObject.ChangeKind.UPDATE);
+ }
+
+ @Override
+ public int numberDeleted() {
+ return numAdaptersOfKind(PublishedObject.ChangeKind.DELETE);
+ }
+
+ private int numAdaptersOfKind(final PublishedObject.ChangeKind kind) {
+ final Collection<ObjectAdapter> objectAdapters = adaptersByChange().get(kind);
+ return objectAdapters != null ? objectAdapters.size() : 0;
+ }
+
+
+ /**
+ * Lazily populated
+ */
+ private Map<PublishedObject.ChangeKind, Collection<ObjectAdapter>> adaptersByChange;
+
+ private Map<PublishedObject.ChangeKind, Collection<ObjectAdapter>> adaptersByChange() {
+ return adaptersByChange != null? adaptersByChange : (adaptersByChange = invert(changesByAdapter));
+ }
+
+ private static <T, S> Map<T, Collection<S>> invert(final Map<S, T> valueByKey) {
+ return new TreeMap<>(
+ Multimaps.invertFrom(
+ Multimaps.forMap(valueByKey),
+ ArrayListMultimap.<T, S>create()
+ ).asMap()
+ );
+ }
+
+ //endregion
+
+
+ //region > newDto, newObjectsDto, newChangesDto
+
+ private ChangesDto newDto() {
+ final ObjectsDto objectsDto = newObjectsDto();
+ return newChangesDto(objectsDto);
+ }
+
+ protected ObjectsDto newObjectsDto() {
+
+ final ObjectsDto objectsDto = new ObjectsDto();
+
+ objectsDto.setCreated(oidsDtoFor(PublishedObject.ChangeKind.CREATE));
+ objectsDto.setUpdated(oidsDtoFor(PublishedObject.ChangeKind.UPDATE));
+ objectsDto.setDeleted(oidsDtoFor(PublishedObject.ChangeKind.DELETE));
+
+ return objectsDto;
+ }
+
+ private OidsDto oidsDtoFor(final PublishedObject.ChangeKind kind) {
+ final OidsDto oidsDto = new OidsDto();
+
+ final Map<PublishedObject.ChangeKind, Collection<ObjectAdapter>> adaptersByChange = adaptersByChange();
+
+ final Collection<ObjectAdapter> adapters = adaptersByChange.get(kind);
+ if(adapters != null) {
+ final ImmutableList<OidDto> oidDtos = FluentIterable.from(adapters)
+ .transform(new Function<ObjectAdapter, OidDto>() {
+ @Override
+ public OidDto apply(final ObjectAdapter objectAdapter) {
+ final RootOid rootOid = (RootOid) objectAdapter.getOid();
+ return rootOid.asOidDto();
+ }
+ })
+ .toList();
+ oidsDto.getOid().addAll(oidDtos);
+ }
+ return oidsDto;
+ }
+
+ protected ChangesDto newChangesDto(final ObjectsDto objectsDto) {
+ final String transactionId = transactionUuid.toString();
+ final ChangesDto changesDto = new ChangesDto();
+
+ changesDto.setMajorVersion("1");
+ changesDto.setMinorVersion("0");
+
+ changesDto.setTransactionId(transactionId);
+ changesDto.setUser(userName);
+ changesDto.setCompletedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(completedAt));
+ changesDto.setObjects(objectsDto);
+ return changesDto;
+ }
+
+
+ //endregion
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishingServiceInternalDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishingServiceInternalDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishingServiceInternalDefault.java
new file mode 100644
index 0000000..e15a978
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publish/PublishingServiceInternalDefault.java
@@ -0,0 +1,397 @@
+/*
+ * 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.publish;
+
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.Identifier;
+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.PublishedAction;
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.applib.annotation.PublishedObject.ChangeKind;
+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.publish.PublishedObjects;
+import org.apache.isis.applib.services.iactn.Interaction;
+import org.apache.isis.applib.services.iactn.InteractionContext;
+import org.apache.isis.applib.services.publish.EventMetadata;
+import org.apache.isis.applib.services.publish.EventPayload;
+import org.apache.isis.applib.services.publish.EventType;
+import org.apache.isis.applib.services.publish.ObjectStringifier;
+import org.apache.isis.applib.services.publish.PublisherService;
+import org.apache.isis.applib.services.publish.PublishingService;
+import org.apache.isis.applib.services.user.UserService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.FacetedMethodParameter;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
+import org.apache.isis.core.metamodel.facets.actions.publish.PublishedActionFacet;
+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.ixn.InteractionDtoServiceInternal;
+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.changes.ChangedObjectsServiceInternal;
+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;
+
+/**
+ * Wrapper around {@link PublishingService}. Is a no-op if there is no injected service.
+ */
+@DomainService(nature = NatureOfService.DOMAIN)
+public class PublishingServiceInternalDefault implements PublishingServiceInternal {
+
+ private final static Function<ObjectAdapter, ObjectAdapter> NOT_DESTROYED_ELSE_EMPTY = new Function<ObjectAdapter, ObjectAdapter>() {
+ public ObjectAdapter apply(ObjectAdapter adapter) {
+ if(adapter == null) {
+ return null;
+ }
+ if (!adapter.isDestroyed()) {
+ return adapter;
+ }
+ // objectstores such as JDO prevent the underlying pojo from being touched once it has been deleted.
+ // we therefore replace that pojo with an 'empty' one.
+
+ Object replacementObject = getPersistenceSession().instantiateAndInjectServices(adapter.getSpecification());
+ getPersistenceSession().remapRecreatedPojo(adapter, replacementObject);
+ return adapter;
+ }
+ protected PersistenceSession getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+ };
+
+ @Programmatic
+ public static EventType eventTypeFor(ChangeKind changeKind) {
+ if(changeKind == ChangeKind.UPDATE) {
+ return EventType.OBJECT_UPDATED;
+ }
+ if(changeKind == ChangeKind.CREATE) {
+ return EventType.OBJECT_CREATED;
+ }
+ if(changeKind == ChangeKind.DELETE) {
+ return EventType.OBJECT_DELETED;
+ }
+ throw new IllegalArgumentException("unknown ChangeKind '" + changeKind + "'");
+ }
+
+ @Override
+ @Programmatic
+ public void publishObjects() {
+ // take a copy of enlisted adapters ... the JDO implementation of the PublishingService
+ // creates further entities which would be enlisted; taking copy of the map avoids ConcurrentModificationException
+ final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter = Maps.newHashMap();
+ changeKindByEnlistedAdapter.putAll(changedObjectsServiceInternal.getChangeKindByEnlistedAdapter());
+
+ publishObjectsToPublishingService(changeKindByEnlistedAdapter);
+ publishObjectsToPublisherServices(changeKindByEnlistedAdapter);
+ }
+
+ private void publishObjectsToPublishingService(final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter) {
+
+ if(publishingServiceIfAny == null) {
+ return;
+ }
+
+ final String currentUser = userService.getUser().getName();
+ final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
+ final ObjectStringifier stringifier = objectStringifier();
+
+ for (final Map.Entry<ObjectAdapter, ChangeKind> adapterAndChange : changeKindByEnlistedAdapter.entrySet()) {
+ final ObjectAdapter enlistedAdapter = adapterAndChange.getKey();
+ final ChangeKind changeKind = adapterAndChange.getValue();
+
+ publishObjectToPublishingService(
+ enlistedAdapter, changeKind, currentUser, timestamp, stringifier);
+ }
+ }
+
+ private void publishObjectToPublishingService(
+ final ObjectAdapter enlistedAdapter,
+ final ChangeKind changeKind,
+ final String currentUser,
+ final Timestamp timestamp,
+ final ObjectStringifier stringifier) {
+
+ final PublishedObjectFacet publishedObjectFacet =
+ enlistedAdapter.getSpecification().getFacet(PublishedObjectFacet.class);
+ if(publishedObjectFacet == null) {
+ return;
+ }
+
+ final PublishedObject.PayloadFactory payloadFactory = publishedObjectFacet.value();
+
+ final RootOid enlistedAdapterOid = (RootOid) enlistedAdapter.getOid();
+ final String enlistedAdapterClass = CommandUtil.targetClassNameFor(enlistedAdapter);
+ final Bookmark enlistedTarget = enlistedAdapterOid.asBookmark();
+
+ final EventMetadata metadata = newEventMetadata(
+ currentUser, timestamp, changeKind, enlistedAdapterClass, enlistedTarget);
+
+ final Object pojo = ObjectAdapter.Util.unwrap(undeletedElseEmpty(enlistedAdapter));
+ final EventPayload payload = payloadFactory.payloadFor(pojo, changeKind);
+
+ payload.withStringifier(stringifier);
+ publishingServiceIfAny.publish(metadata, payload);
+ }
+
+ private void publishObjectsToPublisherServices(
+ final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter) {
+
+ final Map<ObjectAdapter, ChangeKind> changeKindByPublishedAdapter =
+ Maps.filterKeys(
+ changeKindByEnlistedAdapter,
+ PublishedObjectFacet.Predicates.isPublished());
+
+ if(changeKindByPublishedAdapter.isEmpty()) {
+ return;
+ }
+
+ final PublishedObjects publishedObjects = newPublishedObjects(changeKindByPublishedAdapter);
+
+ for (PublisherService publisherService : publisherServices) {
+ publisherService.publish(publishedObjects);
+ }
+ }
+
+ private PublishedObjects newPublishedObjects(final Map<ObjectAdapter, ChangeKind> changeKindByPublishedAdapter) {
+
+ final Command command = commandContext.getCommand();
+ final UUID transactionUuid = command.getTransactionId();
+
+ final String userName = userService.getUser().getName();
+ final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
+
+ return new PublishedObjectsDefault(transactionUuid, userName, timestamp, changeKindByPublishedAdapter);
+ }
+
+
+
+ @Programmatic
+ public void publishAction(
+ final Interaction.Execution execution,
+ final ObjectAction objectAction,
+ final IdentifiedHolder identifiedHolder,
+ final ObjectAdapter targetAdapter,
+ final List<ObjectAdapter> parameterAdapters,
+ final ObjectAdapter resultAdapter) {
+
+ publishActionToPublishingService(
+ objectAction, identifiedHolder, targetAdapter, parameterAdapters, resultAdapter
+ );
+
+ publishToPublisherServices(execution);
+ }
+
+ @Override
+ public void publishProperty(
+ final Interaction.Execution execution) {
+
+ publishToPublisherServices(execution);
+ }
+
+ private void publishActionToPublishingService(
+ final ObjectAction objectAction,
+ final IdentifiedHolder identifiedHolder,
+ final ObjectAdapter targetAdapter,
+ final List<ObjectAdapter> parameterAdapters,
+ final ObjectAdapter resultAdapter) {
+ if(publishingServiceIfAny == null) {
+ return;
+ }
+ final String currentUser = userService.getUser().getName();
+ final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
+
+ final PublishedActionFacet publishedActionFacet =
+ identifiedHolder.getFacet(PublishedActionFacet.class);
+ if(publishedActionFacet == null) {
+ return;
+ }
+
+ final RootOid adapterOid = (RootOid) targetAdapter.getOid();
+ final String oidStr = getOidMarshaller().marshal(adapterOid);
+ final Identifier actionIdentifier = objectAction.getIdentifier();
+ final String title = oidStr + ": " + actionIdentifier.toNameParmsIdentityString();
+
+ final String actionTargetClass = CommandUtil.targetClassNameFor(targetAdapter);
+ final String actionTargetAction = CommandUtil.targetMemberNameFor(objectAction);
+ final Bookmark actionTarget = CommandUtil.bookmarkFor(targetAdapter);
+ final String actionMemberIdentifier = CommandUtil.memberIdentifierFor(objectAction);
+
+ final List<String> parameterNames;
+ final List<Class<?>> parameterTypes;
+ final Class<?> returnType;
+
+ if(identifiedHolder instanceof FacetedMethod) {
+ // should always be the case
+
+ final FacetedMethod facetedMethod = (FacetedMethod) identifiedHolder;
+ returnType = facetedMethod.getType();
+
+ final List<FacetedMethodParameter> parameters = facetedMethod.getParameters();
+ parameterNames = immutableList(Iterables.transform(parameters, FacetedMethodParameter.Functions.GET_NAME));
+ parameterTypes = immutableList(Iterables.transform(parameters, FacetedMethodParameter.Functions.GET_TYPE));
+ } else {
+ parameterNames = null;
+ parameterTypes = null;
+ returnType = null;
+ }
+
+ final Interaction interaction = interactionContext.getInteraction();
+
+ final int nextEventSequence = interaction.next(Interaction.Sequence.PUBLISHED_EVENT.id());
+ final UUID transactionId = interaction.getTransactionId();
+ final EventMetadata metadata = new EventMetadata(
+ transactionId, nextEventSequence, EventType.ACTION_INVOCATION, currentUser, timestamp, title,
+ actionTargetClass, actionTargetAction, actionTarget, actionMemberIdentifier, parameterNames,
+ parameterTypes, returnType);
+
+ final PublishedAction.PayloadFactory payloadFactory = publishedActionFacet.value();
+
+ final ObjectStringifier stringifier = objectStringifier();
+
+ final EventPayload payload = payloadFactory.payloadFor(
+ identifiedHolder.getIdentifier(),
+ ObjectAdapter.Util.unwrap(undeletedElseEmpty(targetAdapter)),
+ ObjectAdapter.Util.unwrap(undeletedElseEmpty(parameterAdapters)),
+ ObjectAdapter.Util.unwrap(undeletedElseEmpty(resultAdapter)));
+ payload.withStringifier(stringifier);
+ publishingServiceIfAny.publish(metadata, payload);
+ }
+
+ private static <T> List<T> immutableList(final Iterable<T> iterable) {
+ return Collections.unmodifiableList(Lists.newArrayList(iterable));
+ }
+
+ private ObjectStringifier objectStringifier() {
+ return new ObjectStringifier() {
+ @Override
+ public String toString(Object object) {
+ if(object == null) {
+ return null;
+ }
+ final ObjectAdapter adapter = IsisContext.getPersistenceSession().adapterFor(object);
+ Oid oid = adapter.getOid();
+ return oid != null? oid.enString(getOidMarshaller()): encodedValueOf(adapter);
+ }
+ private String encodedValueOf(ObjectAdapter adapter) {
+ EncodableFacet facet = adapter.getSpecification().getFacet(EncodableFacet.class);
+ return facet != null? facet.toEncodedString(adapter): adapter.toString();
+ }
+ @Override
+ public String classNameOf(Object object) {
+ final ObjectAdapter adapter = getPersistenceSession().adapterFor(object);
+ final String className = adapter.getSpecification().getFullIdentifier();
+ return className;
+ }
+ };
+ }
+
+ private static List<ObjectAdapter> undeletedElseEmpty(List<ObjectAdapter> parameters) {
+ return Lists.newArrayList(Iterables.transform(parameters, NOT_DESTROYED_ELSE_EMPTY));
+ }
+
+ private static ObjectAdapter undeletedElseEmpty(ObjectAdapter adapter) {
+ return NOT_DESTROYED_ELSE_EMPTY.apply(adapter);
+ }
+
+ protected OidMarshaller getOidMarshaller() {
+ return IsisContext.getOidMarshaller();
+ }
+
+ private EventMetadata newEventMetadata(
+ final String currentUser,
+ final Timestamp timestamp,
+ final ChangeKind changeKind,
+ final String enlistedAdapterClass,
+ final Bookmark enlistedTarget) {
+ final EventType eventType = PublishingServiceInternalDefault.eventTypeFor(changeKind);
+
+ final Interaction interaction = interactionContext.getInteraction();
+
+ final int nextEventSequence = interaction.next(Interaction.Sequence.PUBLISHED_EVENT.id());
+ final UUID transactionId = interaction.getTransactionId();
+ return new EventMetadata(
+ transactionId, nextEventSequence, eventType, currentUser, timestamp, enlistedTarget.toString(),
+ enlistedAdapterClass, null, enlistedTarget, null, null, null, null);
+ }
+
+ private void publishToPublisherServices(final Interaction.Execution<?,?> execution) {
+
+ if(publisherServices == null || publisherServices.isEmpty()) {
+ return;
+ }
+
+ for (final PublisherService publisherService : publisherServices) {
+ publisherService.publish(execution);
+ }
+ }
+
+ @Inject
+ private List<PublisherService> publisherServices;
+
+ @Inject
+ private PublishingService publishingServiceIfAny;
+
+ @Inject
+ private ChangedObjectsServiceInternal changedObjectsServiceInternal;
+
+ @Inject
+ private InteractionDtoServiceInternal interactionDtoServiceInternal;
+
+ @Inject
+ private CommandContext commandContext;
+
+ @Inject
+ private InteractionContext interactionContext;
+
+ @Inject
+ private ClockService clockService;
+
+ @Inject
+ private UserService userService;
+
+
+ private IsisTransactionManager.PersistenceSessionTransactionManagement getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/ea7c1904/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
deleted file mode 100644
index 870cd21..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
+++ /dev/null
@@ -1,394 +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.sql.Timestamp;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.inject.Inject;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import org.apache.isis.applib.Identifier;
-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.PublishedAction;
-import org.apache.isis.applib.annotation.PublishedObject;
-import org.apache.isis.applib.annotation.PublishedObject.ChangeKind;
-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.changes.ChangedObjects;
-import org.apache.isis.applib.services.iactn.Interaction;
-import org.apache.isis.applib.services.iactn.InteractionContext;
-import org.apache.isis.applib.services.publish.EventMetadata;
-import org.apache.isis.applib.services.publish.EventPayload;
-import org.apache.isis.applib.services.publish.EventType;
-import org.apache.isis.applib.services.publish.ObjectStringifier;
-import org.apache.isis.applib.services.publish.PublisherService;
-import org.apache.isis.applib.services.publish.PublishingService;
-import org.apache.isis.applib.services.user.UserService;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.oid.Oid;
-import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
-import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
-import org.apache.isis.core.metamodel.facets.FacetedMethod;
-import org.apache.isis.core.metamodel.facets.FacetedMethodParameter;
-import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
-import org.apache.isis.core.metamodel.facets.actions.publish.PublishedActionFacet;
-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.ixn.InteractionDtoServiceInternal;
-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.changes.ChangedObjectsDefault;
-import org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal;
-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;
-
-/**
- * Wrapper around {@link PublishingService}. Is a no-op if there is no injected service.
- */
-@DomainService(nature = NatureOfService.DOMAIN)
-public class PublishingServiceInternalDefault implements PublishingServiceInternal {
-
- private final static Function<ObjectAdapter, ObjectAdapter> NOT_DESTROYED_ELSE_EMPTY = new Function<ObjectAdapter, ObjectAdapter>() {
- public ObjectAdapter apply(ObjectAdapter adapter) {
- if(adapter == null) {
- return null;
- }
- if (!adapter.isDestroyed()) {
- return adapter;
- }
- // objectstores such as JDO prevent the underlying pojo from being touched once it has been deleted.
- // we therefore replace that pojo with an 'empty' one.
-
- Object replacementObject = getPersistenceSession().instantiateAndInjectServices(adapter.getSpecification());
- getPersistenceSession().remapRecreatedPojo(adapter, replacementObject);
- return adapter;
- }
- protected PersistenceSession getPersistenceSession() {
- return IsisContext.getPersistenceSession();
- }
-
- };
-
- @Programmatic
- public static EventType eventTypeFor(ChangeKind changeKind) {
- if(changeKind == ChangeKind.UPDATE) {
- return EventType.OBJECT_UPDATED;
- }
- if(changeKind == ChangeKind.CREATE) {
- return EventType.OBJECT_CREATED;
- }
- if(changeKind == ChangeKind.DELETE) {
- return EventType.OBJECT_DELETED;
- }
- throw new IllegalArgumentException("unknown ChangeKind '" + changeKind + "'");
- }
-
- @Override
- @Programmatic
- public void publishObjects() {
-
- // take a copy of enlisted adapters ... the JDO implementation of the PublishingService
- // creates further entities which would be enlisted; taking copy of the map avoids ConcurrentModificationException
- final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter = Maps.newHashMap();
- changeKindByEnlistedAdapter.putAll(changedObjectsServiceInternal.getChangeKindByEnlistedAdapter());
-
- publishObjectsToPublishingService(changeKindByEnlistedAdapter);
- publishObjectsToPublisherServices(changeKindByEnlistedAdapter);
- }
-
- private void publishObjectsToPublishingService(final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter) {
-
- if(publishingServiceIfAny == null) {
- return;
- }
-
- final String currentUser = userService.getUser().getName();
- final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
- final ObjectStringifier stringifier = objectStringifier();
-
- for (final Map.Entry<ObjectAdapter, ChangeKind> adapterAndChange : changeKindByEnlistedAdapter.entrySet()) {
- final ObjectAdapter enlistedAdapter = adapterAndChange.getKey();
- final ChangeKind changeKind = adapterAndChange.getValue();
-
- publishObjectToPublishingService(
- enlistedAdapter, changeKind, currentUser, timestamp, stringifier);
- }
- }
-
- private void publishObjectToPublishingService(
- final ObjectAdapter enlistedAdapter,
- final ChangeKind changeKind,
- final String currentUser,
- final Timestamp timestamp,
- final ObjectStringifier stringifier) {
-
- final PublishedObjectFacet publishedObjectFacet =
- enlistedAdapter.getSpecification().getFacet(PublishedObjectFacet.class);
- if(publishedObjectFacet == null) {
- return;
- }
-
- final PublishedObject.PayloadFactory payloadFactory = publishedObjectFacet.value();
-
- final RootOid enlistedAdapterOid = (RootOid) enlistedAdapter.getOid();
- final String enlistedAdapterClass = CommandUtil.targetClassNameFor(enlistedAdapter);
- final Bookmark enlistedTarget = enlistedAdapterOid.asBookmark();
-
- final EventMetadata metadata = newEventMetadata(
- currentUser, timestamp, changeKind, enlistedAdapterClass, enlistedTarget);
-
- final Object pojo = ObjectAdapter.Util.unwrap(undeletedElseEmpty(enlistedAdapter));
- final EventPayload payload = payloadFactory.payloadFor(pojo, changeKind);
-
- payload.withStringifier(stringifier);
- publishingServiceIfAny.publish(metadata, payload);
- }
-
- private void publishObjectsToPublisherServices(
- final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter) {
-
- if(changeKindByEnlistedAdapter.isEmpty()) {
- return;
- }
-
- final ChangedObjects changedObjects = newEnlistedObjects(changeKindByEnlistedAdapter);
-
- for (PublisherService publisherService : publisherServices) {
- publisherService.publish(changedObjects);
- }
- }
-
- private ChangedObjects newEnlistedObjects(final Map<ObjectAdapter, ChangeKind> changeKindByEnlistedAdapter) {
-
- final Command command = commandContext.getCommand();
- final UUID transactionUuid = command.getTransactionId();
-
- final String userName = userService.getUser().getName();
- final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
-
- return new ChangedObjectsDefault(transactionUuid, userName, timestamp, changeKindByEnlistedAdapter);
- }
-
-
-
- @Programmatic
- public void publishAction(
- final Interaction.Execution execution,
- final ObjectAction objectAction,
- final IdentifiedHolder identifiedHolder,
- final ObjectAdapter targetAdapter,
- final List<ObjectAdapter> parameterAdapters,
- final ObjectAdapter resultAdapter) {
-
- publishActionToPublishingService(
- objectAction, identifiedHolder, targetAdapter, parameterAdapters, resultAdapter
- );
-
- publishToPublisherServices(execution);
- }
-
- @Override
- public void publishProperty(
- final Interaction.Execution execution) {
-
- publishToPublisherServices(execution);
- }
-
- private void publishActionToPublishingService(
- final ObjectAction objectAction,
- final IdentifiedHolder identifiedHolder,
- final ObjectAdapter targetAdapter,
- final List<ObjectAdapter> parameterAdapters,
- final ObjectAdapter resultAdapter) {
- if(publishingServiceIfAny == null) {
- return;
- }
- final String currentUser = userService.getUser().getName();
- final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
-
- final PublishedActionFacet publishedActionFacet =
- identifiedHolder.getFacet(PublishedActionFacet.class);
- if(publishedActionFacet == null) {
- return;
- }
-
- final RootOid adapterOid = (RootOid) targetAdapter.getOid();
- final String oidStr = getOidMarshaller().marshal(adapterOid);
- final Identifier actionIdentifier = objectAction.getIdentifier();
- final String title = oidStr + ": " + actionIdentifier.toNameParmsIdentityString();
-
- final String actionTargetClass = CommandUtil.targetClassNameFor(targetAdapter);
- final String actionTargetAction = CommandUtil.targetMemberNameFor(objectAction);
- final Bookmark actionTarget = CommandUtil.bookmarkFor(targetAdapter);
- final String actionMemberIdentifier = CommandUtil.memberIdentifierFor(objectAction);
-
- final List<String> parameterNames;
- final List<Class<?>> parameterTypes;
- final Class<?> returnType;
-
- if(identifiedHolder instanceof FacetedMethod) {
- // should always be the case
-
- final FacetedMethod facetedMethod = (FacetedMethod) identifiedHolder;
- returnType = facetedMethod.getType();
-
- final List<FacetedMethodParameter> parameters = facetedMethod.getParameters();
- parameterNames = immutableList(Iterables.transform(parameters, FacetedMethodParameter.Functions.GET_NAME));
- parameterTypes = immutableList(Iterables.transform(parameters, FacetedMethodParameter.Functions.GET_TYPE));
- } else {
- parameterNames = null;
- parameterTypes = null;
- returnType = null;
- }
-
- final Interaction interaction = interactionContext.getInteraction();
-
- final int nextEventSequence = interaction.next(Interaction.Sequence.PUBLISHED_EVENT.id());
- final UUID transactionId = interaction.getTransactionId();
- final EventMetadata metadata = new EventMetadata(
- transactionId, nextEventSequence, EventType.ACTION_INVOCATION, currentUser, timestamp, title,
- actionTargetClass, actionTargetAction, actionTarget, actionMemberIdentifier, parameterNames,
- parameterTypes, returnType);
-
- final PublishedAction.PayloadFactory payloadFactory = publishedActionFacet.value();
-
- final ObjectStringifier stringifier = objectStringifier();
-
- final EventPayload payload = payloadFactory.payloadFor(
- identifiedHolder.getIdentifier(),
- ObjectAdapter.Util.unwrap(undeletedElseEmpty(targetAdapter)),
- ObjectAdapter.Util.unwrap(undeletedElseEmpty(parameterAdapters)),
- ObjectAdapter.Util.unwrap(undeletedElseEmpty(resultAdapter)));
- payload.withStringifier(stringifier);
- publishingServiceIfAny.publish(metadata, payload);
- }
-
- private static <T> List<T> immutableList(final Iterable<T> iterable) {
- return Collections.unmodifiableList(Lists.newArrayList(iterable));
- }
-
- private ObjectStringifier objectStringifier() {
- return new ObjectStringifier() {
- @Override
- public String toString(Object object) {
- if(object == null) {
- return null;
- }
- final ObjectAdapter adapter = IsisContext.getPersistenceSession().adapterFor(object);
- Oid oid = adapter.getOid();
- return oid != null? oid.enString(getOidMarshaller()): encodedValueOf(adapter);
- }
- private String encodedValueOf(ObjectAdapter adapter) {
- EncodableFacet facet = adapter.getSpecification().getFacet(EncodableFacet.class);
- return facet != null? facet.toEncodedString(adapter): adapter.toString();
- }
- @Override
- public String classNameOf(Object object) {
- final ObjectAdapter adapter = getPersistenceSession().adapterFor(object);
- final String className = adapter.getSpecification().getFullIdentifier();
- return className;
- }
- };
- }
-
- private static List<ObjectAdapter> undeletedElseEmpty(List<ObjectAdapter> parameters) {
- return Lists.newArrayList(Iterables.transform(parameters, NOT_DESTROYED_ELSE_EMPTY));
- }
-
- private static ObjectAdapter undeletedElseEmpty(ObjectAdapter adapter) {
- return NOT_DESTROYED_ELSE_EMPTY.apply(adapter);
- }
-
- protected OidMarshaller getOidMarshaller() {
- return IsisContext.getOidMarshaller();
- }
-
- private EventMetadata newEventMetadata(
- final String currentUser,
- final Timestamp timestamp,
- final ChangeKind changeKind,
- final String enlistedAdapterClass,
- final Bookmark enlistedTarget) {
- final EventType eventType = PublishingServiceInternalDefault.eventTypeFor(changeKind);
-
- final Interaction interaction = interactionContext.getInteraction();
-
- final int nextEventSequence = interaction.next(Interaction.Sequence.PUBLISHED_EVENT.id());
- final UUID transactionId = interaction.getTransactionId();
- return new EventMetadata(
- transactionId, nextEventSequence, eventType, currentUser, timestamp, enlistedTarget.toString(),
- enlistedAdapterClass, null, enlistedTarget, null, null, null, null);
- }
-
- private void publishToPublisherServices(final Interaction.Execution<?,?> execution) {
-
- if(publisherServices == null || publisherServices.isEmpty()) {
- return;
- }
-
- for (final PublisherService publisherService : publisherServices) {
- publisherService.publish(execution);
- }
- }
-
- @Inject
- private List<PublisherService> publisherServices;
-
- @Inject
- private PublishingService publishingServiceIfAny;
-
- @Inject
- private ChangedObjectsServiceInternal changedObjectsServiceInternal;
-
- @Inject
- private InteractionDtoServiceInternal interactionDtoServiceInternal;
-
- @Inject
- private CommandContext commandContext;
-
- @Inject
- private InteractionContext interactionContext;
-
- @Inject
- private ClockService clockService;
-
- @Inject
- private UserService userService;
-
-
- private IsisTransactionManager.PersistenceSessionTransactionManagement getPersistenceSession() {
- return IsisContext.getPersistenceSession();
- }
-
-}
[2/2] isis git commit: ISIS-1400: filter out any bulk-only actions.
Posted by da...@apache.org.
ISIS-1400: filter out any bulk-only actions.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/b8d19e67
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/b8d19e67
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/b8d19e67
Branch: refs/heads/ISIS-1291
Commit: b8d19e67d7f24c4a08683d1f77b9c80160d1dec8
Parents: ea7c190
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu May 12 15:51:12 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu May 12 15:51:12 2016 +0100
----------------------------------------------------------------------
.../services/grid/bootstrap3/GridSystemServiceBS3.java | 8 ++++++--
.../actionmenu/entityactions/EntityActionLinkFactory.java | 3 ++-
2 files changed, 8 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/b8d19e67/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
index 8e1eafa..1d51fff 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
@@ -40,6 +40,7 @@ import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.MemberGroupLayout;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.filter.Filters;
import org.apache.isis.applib.layout.component.ActionLayoutData;
import org.apache.isis.applib.layout.component.ActionLayoutDataOwner;
import org.apache.isis.applib.layout.component.CollectionLayoutData;
@@ -173,8 +174,11 @@ public class GridSystemServiceBS3 extends GridSystemServiceAbstract<BS3Grid> {
final Map<String, OneToManyAssociation> oneToManyAssociationById =
ObjectMember.Util.mapById(getOneToManyAssociations(objectSpec));
final Map<String, ObjectAction> objectActionById =
- ObjectMember.Util.mapById(objectSpec.getObjectActions(Contributed.INCLUDED));
-
+ ObjectMember.Util.mapById(
+ FluentIterable
+ .from(objectSpec.getObjectActions(Contributed.INCLUDED))
+ .filter(Filters.asPredicate(ObjectAction.Filters.notBulkOnly()))
+ .toList());
final BS3Grid bs3Grid = (BS3Grid) grid;
http://git-wip-us.apache.org/repos/asf/isis/blob/b8d19e67/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
index 698dcf9..336f27e 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
@@ -56,7 +56,8 @@ public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
final Boolean persistent = objectAdapter.representsPersistent();
if (!persistent) {
- throw new IllegalArgumentException("Object '" + objectAdapter.titleString(null) + "' is not persistent.");
+ throw new IllegalArgumentException(String.format(
+ "Object '%s' is not persistent.", objectAdapter.titleString(null)));
}
// check visibility and whether enabled