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 2013/02/01 18:31:19 UTC
[2/3] ISIS-323: first cut
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/audit/markerifc/AuditableMarkerInterfaceFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/audit/markerifc/AuditableMarkerInterfaceFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/audit/markerifc/AuditableMarkerInterfaceFacetFactory.java
new file mode 100644
index 0000000..0ab519c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/audit/markerifc/AuditableMarkerInterfaceFacetFactory.java
@@ -0,0 +1,45 @@
+/*
+ * 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.metamodel.facets.object.audit.markerifc;
+
+
+import org.apache.isis.applib.marker.Auditable;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+
+
+public class AuditableMarkerInterfaceFacetFactory extends FacetFactoryAbstract {
+
+ public AuditableMarkerInterfaceFacetFactory() {
+ super(FeatureType.OBJECTS_ONLY);
+ }
+
+ @Override
+ public void process(ProcessClassContext processClassContext) {
+ final Class<?> cls = processClassContext.getCls();
+ if(!Auditable.class.isAssignableFrom(cls)) {
+ return;
+ }
+ FacetUtil.addFacet(new AuditableFacetMarkerInterface(
+ processClassContext.getFacetHolder()));
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacet.java
new file mode 100644
index 0000000..f64a668
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacet.java
@@ -0,0 +1,34 @@
+/*
+ * 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.metamodel.facets.object.publish;
+
+import java.util.UUID;
+
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
+
+/**
+ * Indicates that changes to an object's properties are to be published has, specifying the means by which
+ * a canonical event representing these changes should be created.
+ */
+public interface PublishedObjectFacet extends SingleValueFacet<PublishedObject.EventCanonicalizer> {
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacetAbstract.java
new file mode 100644
index 0000000..1fa0cbc
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/publish/PublishedObjectFacetAbstract.java
@@ -0,0 +1,37 @@
+/*
+ * 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.metamodel.facets.object.publish;
+
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+
+public abstract class PublishedObjectFacetAbstract extends SingleValueFacetAbstract<PublishedObject.EventCanonicalizer> implements PublishedObjectFacet {
+
+ public static Class<? extends Facet> type() {
+ return PublishedObjectFacet.class;
+ }
+
+ public PublishedObjectFacetAbstract(final PublishedObject.EventCanonicalizer eventCanonicalizer, final FacetHolder holder) {
+ super(type(), eventCanonicalizer, holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionAnnotationFacetFactory.java
new file mode 100644
index 0000000..7e94563
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionAnnotationFacetFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.progmodel.facets.actions.publish;
+
+import org.apache.isis.applib.annotation.PublishedAction;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.actions.publish.PublishedActionFacet;
+
+public class PublishedActionAnnotationFacetFactory extends FacetFactoryAbstract {
+
+ public PublishedActionAnnotationFacetFactory() {
+ super(FeatureType.ACTIONS_ONLY);
+ }
+
+ @Override
+ public void process(final ProcessMethodContext processMethodContext) {
+ final PublishedAction annotation = Annotations.getAnnotation(processMethodContext.getMethod(), PublishedAction.class);
+ FacetUtil.addFacet(create(annotation, processMethodContext.getFacetHolder()));
+ }
+
+ private PublishedActionFacet create(final PublishedAction annotation, final FacetHolder holder) {
+ return annotation == null ? null : new PublishedActionFacetAnnotation(newEventCanonicalizer(annotation.canonicalizeWith()), holder);
+ }
+
+ private static PublishedAction.EventCanonicalizer newEventCanonicalizer(final Class<? extends PublishedAction.EventCanonicalizer> value) {
+ if(value == null) {
+ return null;
+ }
+ try {
+ return (PublishedAction.EventCanonicalizer) value.newInstance();
+ } catch (final InstantiationException e) {
+ return null;
+ } catch (final IllegalAccessException e) {
+ return null;
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionFacetAnnotation.java
new file mode 100644
index 0000000..c6ce0aa
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/publish/PublishedActionFacetAnnotation.java
@@ -0,0 +1,32 @@
+/*
+ * 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.progmodel.facets.actions.publish;
+
+import org.apache.isis.applib.annotation.PublishedAction;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.publish.PublishedActionFacetAbstract;
+
+public class PublishedActionFacetAnnotation extends PublishedActionFacetAbstract {
+
+ public PublishedActionFacetAnnotation(PublishedAction.EventCanonicalizer eventCanonicalizer, final FacetHolder holder) {
+ super(eventCanonicalizer, holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectAnnotationFacetFactory.java
new file mode 100644
index 0000000..e02d21c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectAnnotationFacetFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.progmodel.facets.object.publish;
+
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.object.publish.PublishedObjectFacet;
+
+public class PublishedObjectAnnotationFacetFactory extends FacetFactoryAbstract {
+
+ public PublishedObjectAnnotationFacetFactory() {
+ super(FeatureType.OBJECTS_ONLY);
+ }
+
+ @Override
+ public void process(ProcessClassContext processClassContext) {
+ super.process(processClassContext);
+ final PublishedObject annotation = Annotations.getAnnotation(processClassContext.getCls(), PublishedObject.class);
+ FacetUtil.addFacet(create(annotation, processClassContext.getFacetHolder()));
+ }
+
+ private PublishedObjectFacet create(final PublishedObject annotation, final FacetHolder holder) {
+ return annotation == null ? null : new PublishedObjectFacetAnnotation(newEventCanonicalizer(annotation.canonicalizeWith()), holder);
+ }
+
+ private static PublishedObject.EventCanonicalizer newEventCanonicalizer(final Class<? extends PublishedObject.EventCanonicalizer> value) {
+ if(value == null) {
+ return null;
+ }
+ try {
+ return (PublishedObject.EventCanonicalizer) value.newInstance();
+ } catch (final InstantiationException e) {
+ return null;
+ } catch (final IllegalAccessException e) {
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectFacetAnnotation.java
new file mode 100644
index 0000000..a939471
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/publish/PublishedObjectFacetAnnotation.java
@@ -0,0 +1,36 @@
+/*
+ * 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.progmodel.facets.object.publish;
+
+import java.util.UUID;
+
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.publish.PublishedObjectFacetAbstract;
+
+public class PublishedObjectFacetAnnotation extends PublishedObjectFacetAbstract {
+
+ public PublishedObjectFacetAnnotation(PublishedObject.EventCanonicalizer eventCanonicalizer, final FacetHolder holder) {
+ super(eventCanonicalizer, holder);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 5bb4242..d92f62a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -19,6 +19,8 @@
package org.apache.isis.progmodels.dflt;
+import org.apache.isis.core.metamodel.facets.object.audit.annotation.AuditableAnnotationFacetFactory;
+import org.apache.isis.core.metamodel.facets.object.audit.markerifc.AuditableMarkerInterfaceFacetFactory;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModelAbstract;
import org.apache.isis.core.progmodel.facets.actions.bulk.annotation.BulkAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.debug.annotation.DebugAnnotationFacetFactory;
@@ -29,6 +31,7 @@ import org.apache.isis.core.progmodel.facets.actions.notcontributed.annotation.N
import org.apache.isis.core.progmodel.facets.actions.notinservicemenu.annotation.NotInServiceMenuAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.notinservicemenu.method.NotInServiceMenuMethodFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.prototype.annotation.PrototypeAnnotationFacetFactory;
+import org.apache.isis.core.progmodel.facets.actions.publish.PublishedActionAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.semantics.ActionSemanticsAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.semantics.ActionSemanticsFallbackFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.semantics.IdempotentAnnotationFacetFactory;
@@ -106,6 +109,7 @@ import org.apache.isis.core.progmodel.facets.object.orderfields.FieldOrderAnnota
import org.apache.isis.core.progmodel.facets.object.parseable.ParseableFacetFactory;
import org.apache.isis.core.progmodel.facets.object.plural.annotation.PluralAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.object.plural.staticmethod.PluralMethodFacetFactory;
+import org.apache.isis.core.progmodel.facets.object.publish.PublishedObjectAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.object.regex.annotation.RegExFacetAnnotationForTypeFacetFactory;
import org.apache.isis.core.progmodel.facets.object.title.TitleMethodFacetFactory;
import org.apache.isis.core.progmodel.facets.object.title.annotation.TitleAnnotationFacetFactory;
@@ -433,6 +437,13 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
// so we can dogfood the NO applib "value" types
addFactory(ValueFacetFactory.class);
+ // services
+ addFactory(AuditableAnnotationFacetFactory.class);
+ addFactory(AuditableMarkerInterfaceFacetFactory.class);
+
+ addFactory(PublishedActionAnnotationFacetFactory.class);
+ addFactory(PublishedObjectAnnotationFacetFactory.class);
+
addFactory(FacetsAnnotationFacetFactory.class);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstallerAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstallerAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstallerAbstract.java
index 21b2960..f5bfe2f 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstallerAbstract.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstallerAbstract.java
@@ -25,20 +25,25 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
-import org.apache.log4j.Logger;
-
import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.annotation.PublishedAction;
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.applib.annotation.PublishedObject.EventCanonicalizer;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.applib.services.publish.CanonicalEvent;
+import org.apache.isis.applib.services.publish.PublishingService;
import org.apache.isis.core.commons.config.InstallerAbstract;
import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ObjectAdapterFactory;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
-import org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault;
import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
@@ -63,12 +68,18 @@ import org.apache.isis.core.runtime.system.persistence.AdapterManagerSpi;
import org.apache.isis.core.runtime.system.persistence.IdentifierGenerator;
import org.apache.isis.core.runtime.system.persistence.IdentifierGeneratorDefault;
import org.apache.isis.core.runtime.system.persistence.ObjectFactory;
-import org.apache.isis.core.runtime.system.persistence.OidGenerator;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
import org.apache.isis.core.runtime.system.transaction.EnlistedObjectDirtying;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.PublishingServiceWithCanonicalizers;
import org.apache.isis.core.runtime.systemdependencyinjector.SystemDependencyInjector;
+import org.apache.log4j.Logger;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
/**
* An abstract implementation of {@link PersistenceMechanismInstaller} that will
@@ -86,6 +97,9 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
private static final String LOGGING_PROPERTY = org.apache.isis.core.runtime.logging.Logger.PROPERTY_ROOT + "persistenceSession";
private static final Logger LOG = Logger.getLogger(PersistenceMechanismInstallerAbstract.class);
+
+
+
private SystemDependencyInjector installerLookup;
public PersistenceMechanismInstallerAbstract(final String name) {
@@ -99,6 +113,10 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
super(type, name);
}
+
+ //////////////////////////////////////////////////////////////////////
+ // createPersistenceSessionFactory
+ //////////////////////////////////////////////////////////////////////
@Override
public PersistenceSessionFactory createPersistenceSessionFactory(final DeploymentType deploymentType) {
@@ -106,6 +124,11 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
}
+ //////////////////////////////////////////////////////////////////////
+ // createPersistenceSession
+ //////////////////////////////////////////////////////////////////////
+
+
/**
* Creates a {@link PersistenceSession} with internal (thread-safe) components obtained from the provided {@link PersistenceSessionFactory}.
*
@@ -114,6 +137,7 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
*/
@Override
public PersistenceSession createPersistenceSession(final PersistenceSessionFactory persistenceSessionFactory) {
+
if (LOG.isDebugEnabled()) {
LOG.debug("installing " + this.getClass().getName());
}
@@ -140,7 +164,7 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
final PersistenceSession persistenceSession =
new PersistenceSession(persistenceSessionFactory, adapterFactory, objectFactory, servicesInjector, identifierGenerator, adapterManager, persistAlgorithm, objectStore);
- final IsisTransactionManager transactionManager = createTransactionManager(persistenceSession, objectStore);
+ final IsisTransactionManager transactionManager = createTransactionManager(persistenceSessionFactory, persistenceSession, objectStore);
ensureThatArg(persistenceSession, is(not(nullValue())));
ensureThatArg(transactionManager, is(not(nullValue())));
@@ -148,11 +172,11 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
persistenceSession.setDirtiableSupport(true);
persistenceSession.setTransactionManager(transactionManager);
- // ... and finally return
return persistenceSession;
}
-
+
+
// ///////////////////////////////////////////
// Mandatory hook methods
// ///////////////////////////////////////////
@@ -177,14 +201,70 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
return new PersistAlgorithmDefault();
}
+
/**
* Hook method to return an {@link IsisTransactionManager}.
*
* <p>
* By default returns a {@link IsisTransactionManager}.
+ * @param persistenceSessionFactory TODO
*/
- protected IsisTransactionManager createTransactionManager(final EnlistedObjectDirtying persistor, final TransactionalResource objectStore) {
- return new IsisTransactionManager(persistor, objectStore);
+ protected IsisTransactionManager createTransactionManager(PersistenceSessionFactory persistenceSessionFactory, final EnlistedObjectDirtying enlistedObjectDirtying, final TransactionalResource transactionalResource) {
+ List<Object> services = persistenceSessionFactory.getServices();
+
+ final AuditingService auditingServiceIfAny = getServiceIfAny(services, AuditingService.class);
+ final PublishingServiceWithCanonicalizers publishingServiceIfAny = getPublishingServiceIfAny(services);
+ return new IsisTransactionManager(enlistedObjectDirtying, transactionalResource, auditingServiceIfAny, publishingServiceIfAny);
+ }
+
+ protected PublishingServiceWithCanonicalizers getPublishingServiceIfAny(List<Object> services) {
+ final PublishingService publishingService = getServiceIfAny(services, PublishingService.class);
+ if(publishingService == null) {
+ return null;
+ }
+
+ PublishedObject.EventCanonicalizer objectEventCanonicalizer = getServiceIfAny(services, PublishedObject.EventCanonicalizer.class);
+ if(objectEventCanonicalizer == null) {
+ objectEventCanonicalizer = newDefaultObjectEventCanonicalizer();
+ }
+
+ PublishedAction.EventCanonicalizer actionEventCanonicalizer = getServiceIfAny(services, PublishedAction.EventCanonicalizer.class);
+ if(actionEventCanonicalizer == null) {
+ actionEventCanonicalizer = newDefaultActionEventCanonicalizer();
+ }
+
+ return new PublishingServiceWithCanonicalizers(publishingService, objectEventCanonicalizer, actionEventCanonicalizer);
+ }
+
+ protected EventCanonicalizer newDefaultObjectEventCanonicalizer() {
+ return new PublishedObject.EventCanonicalizer() {
+ @Override
+ public CanonicalEvent canonicalizeObject(final Object changedObject) {
+ return new CanonicalEvent.Default(oidStrFor(changedObject));
+ }
+ };
+ }
+
+ protected org.apache.isis.applib.annotation.PublishedAction.EventCanonicalizer newDefaultActionEventCanonicalizer() {
+ return new PublishedAction.EventCanonicalizer() {
+
+ @Override
+ public CanonicalEvent canonicalizeAction(Object invokedObject, String actionMethodName, List<Object> args, Object actionResult) {
+ return new CanonicalEvent.Default(oidStrFor(invokedObject + "#" + actionMethodName + appendResultIfAny(actionResult)) );
+ }
+
+ private String appendResultIfAny(Object actionResult) {
+ if(actionResult == null) {
+ return "";
+ }
+ return "=" + oidStrFor(actionResult);
+ }
+ };
+ }
+
+ private static String oidStrFor(final Object changedObject) {
+ final ObjectAdapter adapter = IsisContext.getPersistenceSession().getAdapterManager().adapterFor(changedObject);
+ return adapter.getOid().enString(IsisContext.getOidMarshaller());
}
@@ -287,9 +367,8 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
final String configuredClassName = configuration.getString(PersistenceConstants.DOMAIN_OBJECT_CONTAINER_CLASS_NAME, PersistenceConstants.DOMAIN_OBJECT_CONTAINER_NAME_DEFAULT);
return InstanceUtil.createInstance(configuredClassName, PersistenceConstants.DOMAIN_OBJECT_CONTAINER_NAME_DEFAULT, DomainObjectContainer.class);
}
-
-
+
// ///////////////////////////////////////////
// Non overridable.
// ///////////////////////////////////////////
@@ -317,6 +396,43 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
}
+ // ///////////////////////////////////////////
+ // caching services by type
+ // ///////////////////////////////////////////
+
+ /**
+ * If no key, not yet searched for type; otherwise the {@link Optional} indicates
+ * whether a service was found.
+ */
+ private final Map<Class<?>, Optional<Object>> servicesByType = Maps.newHashMap();
+
+ @SuppressWarnings("unchecked")
+ private <T> T getServiceIfAny(List<Object> services, Class<T> serviceClass) {
+ locateAndCache(services, serviceClass);
+ Optional<T> optionalService = (Optional<T>) servicesByType.get(serviceClass);
+ return optionalService.orNull();
+ }
+
+ private void locateAndCache(List<Object> services, Class<?> serviceClass) {
+ if(servicesByType.containsKey(serviceClass)) {
+ return;
+ }
+
+ final Optional<Object> optionalService = Iterables.tryFind(services, ofType(serviceClass));
+ servicesByType.put(serviceClass, optionalService);
+ }
+
+ private static final Predicate<Object> ofType(final Class<?> cls) {
+ return new Predicate<Object>() {
+ @Override
+ public boolean apply(Object input) {
+ return cls.isAssignableFrom(input.getClass());
+ }
+ };
+ };
+
+
+
// /////////////////////////////////////////////////////
// Dependencies (from setters)
// /////////////////////////////////////////////////////
@@ -336,7 +452,6 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
return installerLookup;
}
-
// /////////////////////////////////////////////////////
// Dependencies (from context)
// /////////////////////////////////////////////////////
@@ -344,8 +459,7 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
protected SpecificationLoaderSpi getSpecificationLoader() {
return IsisContext.getSpecificationLoader();
}
-
-
+
// /////////////////////////////////////////////////////
// Guice
// /////////////////////////////////////////////////////
@@ -354,9 +468,4 @@ public abstract class PersistenceMechanismInstallerAbstract extends InstallerAbs
public List<Class<?>> getTypes() {
return listOf(PersistenceSessionFactory.class);
}
-
-
-
-
-
}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
index 85d87df..cf3680d 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.runtime.persistence;
-import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
import static org.apache.isis.core.commons.ensure.Ensure.ensureThatState;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
@@ -38,7 +37,6 @@ import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
import org.apache.isis.core.runtime.persistence.adaptermanager.PojoRecreator;
import org.apache.isis.core.runtime.system.DeploymentType;
@@ -60,6 +58,7 @@ public class PersistenceSessionFactoryDelegating implements PersistenceSessionFa
private List<Object> serviceList;
+
private Boolean fixturesInstalled;
private PojoRecreator pojoRecreator;
@@ -96,6 +95,7 @@ public class PersistenceSessionFactoryDelegating implements PersistenceSessionFa
// check prereq dependencies injected
ensureThatState(serviceList, is(notNullValue()));
+
// a bit of a workaround, but required if anything in the metamodel (for
// example, a
// ValueSemanticsProvider for a date value type) needs to use the Clock
@@ -142,6 +142,7 @@ public class PersistenceSessionFactoryDelegating implements PersistenceSessionFa
}
+
@Override
public final void shutdown() {
doShutdown();
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/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 46a7543..9983657 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
@@ -30,7 +30,12 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.UUID;
+import org.apache.isis.applib.clock.Clock;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.applib.services.publish.PublishingService;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.components.TransactionScopedComponent;
import org.apache.isis.core.commons.ensure.Ensure;
import org.apache.isis.core.commons.exceptions.IsisException;
@@ -39,6 +44,9 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ResolveState;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
+import org.apache.isis.core.metamodel.facets.object.publish.PublishedObjectFacet;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociationFilters;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
@@ -164,7 +172,6 @@ public class IsisTransaction implements TransactionScopedComponent {
public boolean isComplete() {
return isComplete;
}
-
}
@@ -178,11 +185,22 @@ public class IsisTransaction implements TransactionScopedComponent {
private final UpdateNotifier updateNotifier;
private final List<IsisException> exceptions = Lists.newArrayList();
+ /**
+ * could be null if none has been registered
+ */
+ private final AuditingService auditingService;
+ /**
+ * could be null if none has been registered
+ */
+ private final PublishingServiceWithCanonicalizers publishingService;
+
private State state;
private RuntimeException cause;
+
+ private final UUID guid;
- public IsisTransaction(final IsisTransactionManager transactionManager, final MessageBroker messageBroker, final UpdateNotifier updateNotifier, final TransactionalResource objectStore) {
+ public IsisTransaction(final IsisTransactionManager transactionManager, final MessageBroker messageBroker, final UpdateNotifier updateNotifier, final TransactionalResource objectStore, final AuditingService auditingService, PublishingServiceWithCanonicalizers publishingService) {
ensureThatArg(transactionManager, is(not(nullValue())), "transaction manager is required");
ensureThatArg(messageBroker, is(not(nullValue())), "message broker is required");
@@ -191,6 +209,10 @@ public class IsisTransaction implements TransactionScopedComponent {
this.transactionManager = transactionManager;
this.messageBroker = messageBroker;
this.updateNotifier = updateNotifier;
+ this.auditingService = auditingService;
+ this.publishingService = publishingService;
+
+ this.guid = UUID.randomUUID();
this.state = State.IN_PROGRESS;
@@ -201,6 +223,14 @@ public class IsisTransaction implements TransactionScopedComponent {
}
// ////////////////////////////////////////////////////////////////
+ // GUID
+ // ////////////////////////////////////////////////////////////////
+
+ public final UUID getGuid() {
+ return guid;
+ }
+
+ // ////////////////////////////////////////////////////////////////
// State
// ////////////////////////////////////////////////////////////////
@@ -345,7 +375,6 @@ public class IsisTransaction implements TransactionScopedComponent {
private void doFlush() {
try {
- doAudit(getAuditEntries());
objectStore.execute(Collections.unmodifiableList(commands));
@@ -367,13 +396,65 @@ public class IsisTransaction implements TransactionScopedComponent {
}
- /**
- * Hook method for subtypes to audit as required.
- */
- protected void doAudit(Set<Entry<AdapterAndProperty, PreAndPostValues>> auditEntries) {
- for (Entry<AdapterAndProperty, PreAndPostValues> auditEntry : auditEntries) {
- LOG.info(auditEntry.getKey() + ": " + auditEntry.getValue());
+ protected void doAudit(final Set<Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties) {
+ if(auditingService == null) {
+ return;
+ }
+
+ // else
+ final String currentUser = getAuthenticationSession().getUserName();
+ final long currentTimestampEpoch = currentTimestampEpoch();
+ for (Entry<AdapterAndProperty, PreAndPostValues> auditEntry : changedObjectProperties) {
+ auditChangedProperty(currentUser, currentTimestampEpoch, auditEntry);
+ }
+ }
+
+ protected void doPublish(final Set<ObjectAdapter> changedAdapters) {
+ if(publishingService == null) {
+ return;
+ }
+
+ // else
+ final String currentUser = getAuthenticationSession().getUserName();
+ final long currentTimestampEpoch = currentTimestampEpoch();
+
+ for (ObjectAdapter changedAdapter : changedAdapters) {
+ PublishedObjectFacet publishedObjectFacet = changedAdapter.getSpecification().getFacet(PublishedObjectFacet.class);
+ if(publishedObjectFacet == null) {
+ continue;
+ }
+ publishingService.publishObject(publishedObjectFacet.value(), getGuid(), currentUser, currentTimestampEpoch, changedAdapter);
+ }
+
+ // TODO: use a ThreadLocal on ActionInvocationFacet to determine whether there is also a PublishedActionFacet to handle...
+ }
+
+ private static long currentTimestampEpoch() {
+ return Clock.getTime();
+ }
+
+ private void auditChangedProperty(final String currentUser, final long currentTimestampEpoch, final Entry<AdapterAndProperty, PreAndPostValues> auditEntry) {
+ final AdapterAndProperty aap = auditEntry.getKey();
+ final ObjectAdapter adapter = aap.getAdapter();
+ if(!adapter.getSpecification().containsFacet(AuditableFacet.class)) {
+ return;
}
+ final RootOid oid = (RootOid) adapter.getOid();
+ final String objectType = oid.getObjectSpecId().asString();
+ final String identifier = oid.getIdentifier();
+ final PreAndPostValues papv = auditEntry.getValue();
+ final String preValue = asString(papv.getPre());
+ final String postValue = asString(papv.getPost());
+ auditingService.audit(currentUser, currentTimestampEpoch, objectType, identifier, preValue, postValue);
+ }
+
+ private static String asString(Object object) {
+ return object != null? object.toString(): null;
+ }
+
+
+ protected AuthenticationSession getAuthenticationSession() {
+ return IsisContext.getAuthenticationSession();
}
@@ -399,8 +480,10 @@ public class IsisTransaction implements TransactionScopedComponent {
}
try {
+ doAudit(getChangedObjectProperties());
doFlush();
setState(State.COMMITTED);
+ doPublish(getChangedObjects());
} catch (final RuntimeException ex) {
setAbortCause(ex);
throw ex;
@@ -408,6 +491,9 @@ public class IsisTransaction implements TransactionScopedComponent {
}
+
+
+
// ////////////////////////////////////////////////////////////////
// abort
// ////////////////////////////////////////////////////////////////
@@ -535,6 +621,7 @@ public class IsisTransaction implements TransactionScopedComponent {
}
public static class AdapterAndProperty {
+
private final ObjectAdapter objectAdapter;
private final ObjectAssociation property;
@@ -602,7 +689,7 @@ public class IsisTransaction implements TransactionScopedComponent {
////////////////////////////////////////////////////////////////////////
- // Auditing
+ // Auditing/Publishing object tracking
////////////////////////////////////////////////////////////////////////
public static class PreAndPostValues {
@@ -648,29 +735,54 @@ public class IsisTransaction implements TransactionScopedComponent {
}
- private final Map<AdapterAndProperty, PreAndPostValues> auditLog = Maps.newLinkedHashMap();
+ private final Map<AdapterAndProperty, PreAndPostValues> changedObjectProperties = Maps.newLinkedHashMap();
+ private final Set<ObjectAdapter> changedObjects = Sets.newLinkedHashSet();
+ /**
+ * For object stores to record the current values of an {@link ObjectAdapter} that has enlisted
+ * into the transaction, prior to updating its values.
+ *
+ * <p>
+ * The values of the {@link ObjectAdapter} after being updated are captured when the
+ * audit entries are requested, in {@link #getChangedObjectProperties()}.
+ *
+ * <p>
+ * Supported by the JDO object store; check documentation for support in other objectstores.
+ */
public void auditDirty(ObjectAdapter adapter) {
for (ObjectAssociation property : adapter.getSpecification().getAssociations(ObjectAssociationFilters.PROPERTIES)) {
- audit(adapter, property);
+ changedObjectProperty(adapter, property);
}
}
- private void audit(ObjectAdapter adapter, ObjectAssociation property) {
+ private void changedObjectProperty(ObjectAdapter adapter, ObjectAssociation property) {
final AdapterAndProperty aap = AdapterAndProperty.of(adapter, property);
PreAndPostValues papv = PreAndPostValues.pre(aap.getPropertyValue());
- auditLog.put(aap, papv);
+ changedObjectProperties.put(aap, papv);
+ changedObjects.add(adapter);
}
- public Set<Entry<AdapterAndProperty, PreAndPostValues>> getAuditEntries() {
- updatePostValues(auditLog.entrySet());
+ /**
+ * Returns the pre- and post-values of all {@link ObjectAdapter}s that were enlisted and dirtied
+ * in this transaction.
+ *
+ * <p>
+ * This requires that the object store called {@link #auditDirty(ObjectAdapter)} for each object being
+ * enlisted.
+ *
+ * <p>
+ * Supported by the JDO object store (since it calls {@link #auditDirty(ObjectAdapter)});
+ * check documentation for support in other object stores.
+ */
+ public Set<Entry<AdapterAndProperty, PreAndPostValues>> getChangedObjectProperties() {
+ updatePostValues(changedObjectProperties.entrySet());
- return Collections.unmodifiableSet(Sets.filter(auditLog.entrySet(), PreAndPostValues.CHANGED));
+ return Collections.unmodifiableSet(Sets.filter(changedObjectProperties.entrySet(), PreAndPostValues.CHANGED));
}
- private void updatePostValues(Set<Entry<AdapterAndProperty, PreAndPostValues>> entrySet) {
+ private static void updatePostValues(Set<Entry<AdapterAndProperty, PreAndPostValues>> entrySet) {
for (Entry<AdapterAndProperty, PreAndPostValues> entry : entrySet) {
final AdapterAndProperty aap = entry.getKey();
final PreAndPostValues papv = entry.getValue();
@@ -679,13 +791,15 @@ public class IsisTransaction implements TransactionScopedComponent {
}
}
+ private Set<ObjectAdapter> getChangedObjects() {
+ return changedObjects;
+ }
////////////////////////////////////////////////////////////////////////
// Dependencies (from context)
////////////////////////////////////////////////////////////////////////
-
protected AdapterManager getAdapterManager() {
return IsisContext.getPersistenceSession().getAdapterManager();
}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
index e5d10d8..e8a3305 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
@@ -28,16 +28,19 @@ import static org.hamcrest.CoreMatchers.nullValue;
import java.util.List;
-import org.apache.log4j.Logger;
-
+import org.apache.isis.applib.annotation.PublishedAction;
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.applib.annotation.PublishedObject.EventCanonicalizer;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.applib.services.publish.PublishingService;
import org.apache.isis.core.commons.components.SessionScopedComponent;
import org.apache.isis.core.commons.debug.DebugBuilder;
import org.apache.isis.core.commons.exceptions.IsisException;
-import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
import org.apache.isis.core.runtime.persistence.objectstore.transaction.TransactionalResource;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.session.IsisSession;
+import org.apache.log4j.Logger;
public class IsisTransactionManager implements SessionScopedComponent {
@@ -49,6 +52,15 @@ public class IsisTransactionManager implements SessionScopedComponent {
private int transactionLevel;
+ /**
+ * Could be null.
+ */
+ private final AuditingService auditingService;
+ /**
+ * Could be null.
+ */
+ private final PublishingServiceWithCanonicalizers publishingService;
+
private IsisSession session;
/**
@@ -61,9 +73,11 @@ public class IsisTransactionManager implements SessionScopedComponent {
// constructor
// ////////////////////////////////////////////////////////////////
- public IsisTransactionManager(final EnlistedObjectDirtying objectPersistor, final TransactionalResource objectStore) {
+ public IsisTransactionManager(final EnlistedObjectDirtying objectPersistor, final TransactionalResource objectStore, final AuditingService auditingService, final PublishingServiceWithCanonicalizers publishingService) {
this.objectPersistor = objectPersistor;
this.transactionalResource = objectStore;
+ this.auditingService = auditingService;
+ this.publishingService = publishingService;
}
@@ -234,7 +248,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
ensureThatArg(messageBroker, is(not(nullValue())));
ensureThatArg(updateNotifier, is(not(nullValue())));
- return new IsisTransaction(this, messageBroker, updateNotifier, getTransactionalResource());
+ return new IsisTransaction(this, messageBroker, updateNotifier, getTransactionalResource(), auditingService, publishingService);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/PublishingServiceWithCanonicalizers.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/PublishingServiceWithCanonicalizers.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/PublishingServiceWithCanonicalizers.java
new file mode 100644
index 0000000..df9b597
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/PublishingServiceWithCanonicalizers.java
@@ -0,0 +1,39 @@
+package org.apache.isis.core.runtime.system.transaction;
+
+import java.util.UUID;
+
+import org.apache.isis.applib.annotation.PublishedAction;
+import org.apache.isis.applib.annotation.PublishedObject;
+import org.apache.isis.applib.annotation.PublishedObject.EventCanonicalizer;
+import org.apache.isis.applib.services.publish.CanonicalEvent;
+import org.apache.isis.applib.services.publish.PublishingService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+/**
+ * Wrapper around {@link PublishingService} that also includes the
+ * {@link PublishedObject.EventCanonicalizer event} {@link PublishedAction.EventCanonicalizer canonicalizers}.
+ *
+ * <p>
+ * Acts as an internal contract between {@link IsisTransactionManager} and {@link IsisTransaction}.
+ */
+public class PublishingServiceWithCanonicalizers {
+
+ private final PublishingService publishingService;
+ private final PublishedObject.EventCanonicalizer defaultObjectEventCanonicalizer;
+ private final PublishedAction.EventCanonicalizer defaultActionEventCanonicalizer;
+
+ public PublishingServiceWithCanonicalizers(PublishingService publishingService, EventCanonicalizer defaultObjectEventCanonicalizer, PublishedAction.EventCanonicalizer defaultActionEventCanonicalizer) {
+ this.publishingService = publishingService;
+ this.defaultObjectEventCanonicalizer = defaultObjectEventCanonicalizer;
+ this.defaultActionEventCanonicalizer = defaultActionEventCanonicalizer;
+ }
+
+ public void publishObject(PublishedObject.EventCanonicalizer eventCanonicalizer, UUID guid, String currentUser, long currentTimestampEpoch, ObjectAdapter changedAdapter) {
+ PublishedObject.EventCanonicalizer eventCanonicalizerToUse = eventCanonicalizer != null? eventCanonicalizer: defaultObjectEventCanonicalizer;
+ CanonicalEvent canonicalizedEvent = eventCanonicalizerToUse.canonicalizeObject(changedAdapter.getObject());
+
+ publishingService.publish(guid, currentUser, currentTimestampEpoch, canonicalizedEvent);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
index 524e47c..523af9b 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
@@ -33,6 +33,8 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.applib.services.publish.PublishingService;
import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.commons.matchers.IsisMatchers;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -63,6 +65,7 @@ import org.apache.isis.core.runtime.system.persistence.OidGenerator;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.PublishingServiceWithCanonicalizers;
import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
@@ -93,6 +96,10 @@ public class PersistenceSessionObjectStoreTest {
private ObjectFactory objectFactory;
@Mock
private PersistAlgorithm mockPersistAlgorithm;
+ @Mock
+ private AuditingService mockAuditingService;
+ @Mock
+ private PublishingServiceWithCanonicalizers mockPublishingService;
@Mock
private CreateObjectCommand createObjectCommand;
@@ -128,6 +135,7 @@ public class PersistenceSessionObjectStoreTest {
context.ignoring(mockRuntimeContext);
context.ignoring(mockConfiguration);
+ context.ignoring(mockAuditingService);
isisMetaModel = new IsisMetaModel(mockRuntimeContext, new ProgrammingModelFacetsJava5(), new CustomerRepository());
isisMetaModel.init();
@@ -165,7 +173,7 @@ public class PersistenceSessionObjectStoreTest {
};
- transactionManager = new IsisTransactionManager(persistenceSession, mockObjectStore);
+ transactionManager = new IsisTransactionManager(persistenceSession, mockObjectStore, mockAuditingService, mockPublishingService);
persistenceSession.setTransactionManager(transactionManager);
servicesInjector.setServices(Collections.emptyList());
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManagerAbstractTestCase.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManagerAbstractTestCase.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManagerAbstractTestCase.java
deleted file mode 100644
index b22455e..0000000
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManagerAbstractTestCase.java
+++ /dev/null
@@ -1,67 +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.persistence.objectstore.transaction;
-
-import org.jmock.Expectations;
-import org.junit.Rule;
-
-import org.apache.isis.core.runtime.persistence.objectstore.transaction.TransactionalResource;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-import org.apache.isis.core.runtime.system.session.IsisSession;
-import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
-import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-
-public abstract class ObjectStoreTransactionManagerAbstractTestCase {
-
- @Rule
- public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
- protected IsisTransactionManager transactionManager;
- @Mock
- protected IsisSession mockSession;
- @Mock
- protected PersistenceSession mockPersistenceSession;
- @Mock
- protected TransactionalResource mockObjectStore;
-
-
- // //////////////////////////////////////////////////
- // Helpers
- // //////////////////////////////////////////////////
-
- protected void ignoreCallsToPersistenceSession() {
- context.checking(new Expectations() {
- {
- ignoring(mockPersistenceSession);
- }
- });
- }
-
- protected void ignoreCallsToObjectStore() {
- context.checking(new Expectations() {
- {
- ignoring(mockObjectStore);
- }
- });
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
index 8bb1461..ae29134 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
@@ -25,25 +25,50 @@ import static org.junit.Assert.assertThat;
import java.util.Collections;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.applib.services.publish.PublishingService;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.session.IsisSession;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.PublishingServiceWithCanonicalizers;
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
import org.jmock.Expectations;
import org.jmock.Sequence;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
-import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+public class ObjectStoreTransactionManager_EndTransactionTest {
+
+ @Rule
+ public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+
+ @Mock
+ private IsisSession mockSession;
+ @Mock
+ private PersistenceSession mockPersistenceSession;
+ @Mock
+ private TransactionalResource mockObjectStore;
+
+ @Mock
+ private AuditingService mockAuditingService;
+ @Mock
+ private PublishingServiceWithCanonicalizers mockPublishingService;
-public class ObjectStoreTransactionManager_EndTransactionTest extends ObjectStoreTransactionManagerAbstractTestCase {
+ private IsisTransactionManager transactionManager;
@Before
public void setUpTransactionManager() throws Exception {
- transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore);
+ transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, mockAuditingService, mockPublishingService);
}
@Test
public void endTransactionDecrementsTransactionLevel() throws Exception {
// setup
- ignoreCallsToObjectStore();
+ context.ignoring(mockObjectStore);
transactionManager.startTransaction();
transactionManager.startTransaction();
@@ -55,7 +80,7 @@ public class ObjectStoreTransactionManager_EndTransactionTest extends ObjectStor
@Test
public void endTransactionCommitsTransactionWhenLevelDecrementsDownToZero() throws Exception {
// setup
- ignoreCallsToObjectStore();
+ context.ignoring(mockObjectStore);
transactionManager.startTransaction();
context.checking(new Expectations() {
@@ -71,7 +96,7 @@ public class ObjectStoreTransactionManager_EndTransactionTest extends ObjectStor
@Test
public void startTransactionInteractsWithObjectStore() throws Exception {
// setup
- ignoreCallsToPersistenceSession();
+ context.ignoring(mockPersistenceSession);
context.checking(new Expectations() {
{
@@ -85,7 +110,7 @@ public class ObjectStoreTransactionManager_EndTransactionTest extends ObjectStor
@Test
public void endTransactionInteractsWithObjectStore() throws Exception {
// setup
- ignoreCallsToPersistenceSession();
+ context.ignoring(mockPersistenceSession);
context.checking(new Expectations() {
{
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
index fbff96e..d7618c7 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
@@ -19,15 +19,42 @@
package org.apache.isis.core.runtime.persistence.objectstore.transaction;
+import org.junit.Rule;
import org.junit.Test;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.applib.services.publish.PublishingService;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.session.IsisSession;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.PublishingServiceWithCanonicalizers;
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-public class ObjectStoreTransactionManager_InstantiationTest extends ObjectStoreTransactionManagerAbstractTestCase {
+public class ObjectStoreTransactionManager_InstantiationTest {
+
+ @Rule
+ public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+
+ @Mock
+ private IsisSession mockSession;
+ @Mock
+ private PersistenceSession mockPersistenceSession;
+ @Mock
+ private TransactionalResource mockObjectStore;
+
+ @Mock
+ private AuditingService mockAuditingService;
+ @Mock
+ private PublishingServiceWithCanonicalizers mockPublishingService;
+
+ private IsisTransactionManager transactionManager;
@Test
public void canInstantiate() throws Exception {
- transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore);
+ transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, mockAuditingService, mockPublishingService);
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
index c7205ab..42b01ea 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
@@ -25,28 +25,53 @@ import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.junit.Assert.assertThat;
+import org.apache.isis.applib.services.audit.AuditingService;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.session.IsisSession;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.PublishingServiceWithCanonicalizers;
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
import org.jmock.Expectations;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
-import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+public class ObjectStoreTransactionManager_StartTransactionTest {
+
+ @Rule
+ public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+
+ @Mock
+ private IsisSession mockSession;
+ @Mock
+ private PersistenceSession mockPersistenceSession;
+ @Mock
+ private TransactionalResource mockObjectStore;
+
+ @Mock
+ private AuditingService mockAuditingService;
+ @Mock
+ private PublishingServiceWithCanonicalizers mockPublishingService;
-public class ObjectStoreTransactionManager_StartTransactionTest extends ObjectStoreTransactionManagerAbstractTestCase {
+ private IsisTransactionManager transactionManager;
@Before
public void setUpTransactionManager() throws Exception {
- transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore);
+ transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, mockAuditingService, mockPublishingService);
}
@Before
public void setUpExpectations() throws Exception {
- ignoreCallsToPersistenceSession();
+ context.ignoring(mockPersistenceSession);
}
@Test
public void startTransactionCreateTransactionIfNone() throws Exception {
- ignoreCallsToObjectStore();
+ context.ignoring(mockObjectStore);
assertThat(transactionManager.getTransaction(), is(nullValue()));
transactionManager.startTransaction();
@@ -55,7 +80,7 @@ public class ObjectStoreTransactionManager_StartTransactionTest extends ObjectSt
@Test
public void startTransactionDoesNotOverwriteTransactionIfHasOne() throws Exception {
- ignoreCallsToObjectStore();
+ context.ignoring(mockObjectStore);
// cause a transaction to be created
transactionManager.startTransaction();
@@ -68,7 +93,7 @@ public class ObjectStoreTransactionManager_StartTransactionTest extends ObjectSt
@Test
public void startTransactionIncrementsTransactionLevel() throws Exception {
- ignoreCallsToObjectStore();
+ context.ignoring(mockObjectStore);
assertThat(transactionManager.getTransactionLevel(), is(0));
transactionManager.startTransaction();
http://git-wip-us.apache.org/repos/asf/isis/blob/1f558615/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/TransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/TransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/TransactionTest.java
deleted file mode 100644
index b78c7d2..0000000
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/TransactionTest.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.isis.core.runtime.persistence.objectstore.transaction;
-
-import java.util.Collections;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.hamcrest.CoreMatchers;
-import org.jmock.Expectations;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import org.apache.isis.core.commons.matchers.IsisMatchers;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
-import org.apache.isis.core.runtime.persistence.objectstore.ObjectStoreSpi;
-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.persistence.objectstore.transaction.PersistenceCommandContext;
-import org.apache.isis.core.runtime.persistence.objectstore.transaction.SaveObjectCommand;
-import org.apache.isis.core.runtime.persistence.objectstore.transaction.PojoAdapterBuilder.Persistence;
-import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
-import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
-import org.apache.isis.core.runtime.system.transaction.MessageBroker;
-import org.apache.isis.core.runtime.system.transaction.UpdateNotifier;
-import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-
-public class TransactionTest {
-
- @Rule
- public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
- private IsisTransaction transaction;
-
- private ObjectAdapter transientAdapter1;
- private ObjectAdapter transientAdapter2;
-
- private ObjectAdapter persistentAdapter1;
- private ObjectAdapter persistentAdapter2;
-
- @Mock
- private ObjectStoreSpi mockObjectStore;
-
- @Mock
- private IsisTransactionManager mockTransactionManager;
- @Mock
- private MessageBroker mockMessageBroker;
- @Mock
- private UpdateNotifier mockUpdateNotifier;
-
- private PersistenceCommand command;
- private PersistenceCommand command2;
- private PersistenceCommand command3;
-
- private CreateObjectCommand createCreateCommand(final ObjectAdapter object, final String name) {
- return new CreateObjectCommand() {
-
- @Override
- public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
- }
-
- @Override
- public ObjectAdapter onAdapter() {
- return object;
- }
-
- @Override
- public String toString() {
- return name;
- }
- };
- }
-
- private DestroyObjectCommand createDestroyCommand(final ObjectAdapter object, final String name) {
- return new DestroyObjectCommand() {
-
- @Override
- public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
- }
-
- @Override
- public ObjectAdapter onAdapter() {
- return object;
- }
-
- @Override
- public String toString() {
- return name;
- }
- };
- }
-
- private SaveObjectCommand createSaveCommand(final ObjectAdapter object, final String name) {
- return new SaveObjectCommand() {
- @Override
- public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
- }
-
- @Override
- public ObjectAdapter onAdapter() {
- return object;
- }
-
- @Override
- public String toString() {
- return name;
- }
- };
- }
-
- private SaveObjectCommand createSaveCommandThatAborts(final ObjectAdapter object, final String name) {
- return new SaveObjectCommand() {
- @Override
- public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
- throw new ObjectPersistenceException();
- }
-
- @Override
- public ObjectAdapter onAdapter() {
- return object;
- }
-
- @Override
- public String toString() {
- return name;
- }
- };
- }
-
- @Before
- public void setUp() throws Exception {
- Logger.getRootLogger().setLevel(Level.OFF);
-
- transaction = new IsisTransaction(mockTransactionManager, mockMessageBroker, mockUpdateNotifier, mockObjectStore);
-
- transientAdapter1 = PojoAdapterBuilder.create().with(Persistence.TRANSIENT).withIdentifier("1").build();
- transientAdapter2 = PojoAdapterBuilder.create().with(Persistence.TRANSIENT).withIdentifier("2").build();
- persistentAdapter1 = PojoAdapterBuilder.create().with(Persistence.PERSISTENT).withIdentifier("3").build();
- persistentAdapter2 = PojoAdapterBuilder.create().with(Persistence.PERSISTENT).withIdentifier("4").build();
- }
-
- @Test
- public void abort_neverDelegatesToObjectStore() throws Exception {
-
- command = createSaveCommand(transientAdapter1, "command 1");
- command2 = createSaveCommand(transientAdapter2, "command 2");
-
- context.checking(new Expectations() {
- {
- never(mockObjectStore);
- }
- });
-
- transaction.addCommand(command);
- transaction.addCommand(command2);
- transaction.abort();
- }
-
-
- @Test
- public void commit_delegatesToObjectStoreToExecutesAllCommands() throws Exception {
-
- command = createSaveCommand(transientAdapter1, "command 1");
- command2 = createSaveCommandThatAborts(transientAdapter2, "command 2");
-
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(IsisMatchers.listContainingAll(command, command2)));
- }
- });
-
- transaction.addCommand(command);
- transaction.addCommand(command2);
- transaction.commit();
- }
-
- @Test
- public void commit_disregardsSecondSaveCommandOnSameAdapter() throws Exception {
-
- command = createSaveCommand(persistentAdapter1, "command 1");
- command2 = createSaveCommand(persistentAdapter1, "command 2");
-
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(IsisMatchers.listContainingAll(command)));
- }
- });
-
- transaction.addCommand(command);
- transaction.addCommand(command2);
- transaction.commit();
- }
-
-
- @Test
- public void commit_disregardsSaveCommandsForObjectBeingCreated() throws Exception {
-
- command = createCreateCommand(transientAdapter1, "command 1");
- command2 = createSaveCommandThatAborts(transientAdapter1, "command 2");
-
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(IsisMatchers.listContainingAll(command)));
- }
- });
-
- transaction.addCommand(command);
- transaction.addCommand(command2);
- transaction.commit();
- }
-
- @Test
- public void commit_destroyCausesPrecedingSaveCommandsToBeDisregarded() throws Exception {
-
- command = createSaveCommand(persistentAdapter1, "command 1");
- command2 = createSaveCommand(persistentAdapter2, "command 2");
- command3 = createDestroyCommand(persistentAdapter1, "command 3");
-
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(IsisMatchers.listContainingAll(command2, command3)));
- }
- });
-
- transaction.addCommand(command);
- transaction.addCommand(command2);
- transaction.addCommand(command3);
- transaction.commit();
- }
-
- @Test
- public void commit_ignoresBothCreateAndDestroyCommandsWhenForSameObject() throws Exception {
-
- command = createSaveCommand(persistentAdapter1, "command 1");
- command2 = createSaveCommand(persistentAdapter2, "command 2");
- command3 = createDestroyCommand(persistentAdapter1, "command 3");
-
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(IsisMatchers.listContainingAll(command2)));
- }
- });
-
- transaction.addCommand(command);
- transaction.addCommand(command2);
- transaction.addCommand(command3);
- transaction.commit();
- }
-
-
- @Test
- public void commit_testNoCommands() throws Exception {
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(Collections.<PersistenceCommand>emptyList()));
- }
- });
-
- transaction.commit();
- }
-
-
- @Test(expected = IllegalStateException.class)
- public void shouldThrowExceptionIfAttemptToAbortAnAlreadyAbortedTransaction() throws Exception {
- transaction.abort();
-
- transaction.abort();
- }
-
- @Test(expected = IllegalStateException.class)
- public void shouldThrowExceptionIfAttemptToCommitAnAlreadyAbortedTransaction() throws Exception {
- transaction.abort();
-
- transaction.commit();
- }
-
- @Test(expected = IllegalStateException.class)
- public void shouldThrowExceptionIfAttemptToAbortAnAlreadyCommitedTransaction() throws Exception {
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(Collections.<PersistenceCommand>emptyList()));
- }
- });
-
- transaction.commit();
-
- transaction.abort();
- }
-
- @Test(expected = IllegalStateException.class)
- public void shouldThrowExceptionIfAttemptToCommitAnAlreadyCommitedTransaction() throws Exception {
- context.checking(new Expectations() {
- {
- one(mockObjectStore).execute(with(Collections.<PersistenceCommand>emptyList()));
- }
- });
- transaction.commit();
-
- transaction.commit();
- }
-}