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 2014/07/04 14:46:52 UTC
[10/12] ISIS-833: moved applib services into own modules,
rationalized most of the applib/runtime modules
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java
new file mode 100644
index 0000000..097f64c
--- /dev/null
+++ b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdo.java
@@ -0,0 +1,490 @@
+/*
+ * 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.objectstore.jdo.applib.service.publish;
+
+import java.util.UUID;
+import javax.jdo.annotations.IdentityType;
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.*;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.services.HasTransactionId;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.publish.EventType;
+import org.apache.isis.applib.util.ObjectContracts;
+import org.apache.isis.applib.util.TitleBuffer;
+import org.apache.isis.objectstore.jdo.applib.service.DomainChangeJdoAbstract;
+import org.apache.isis.objectstore.jdo.applib.service.JdoColumnLength;
+import org.apache.isis.objectstore.jdo.applib.service.Util;
+
+@javax.jdo.annotations.PersistenceCapable(
+ identityType=IdentityType.APPLICATION,
+ table="IsisPublishedEvent",
+ objectIdClass=PublishedEventJdoPK.class)
+@javax.jdo.annotations.Queries( {
+ @javax.jdo.annotations.Query(
+ name="findByStateOrderByTimestamp", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE state == :state "
+ + "ORDER BY timestamp"),
+ @javax.jdo.annotations.Query(
+ name="findByTransactionId", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE transactionId == :transactionId"),
+ @javax.jdo.annotations.Query(
+ name="findByTargetAndTimestampBetween", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE targetStr == :targetStr "
+ + "&& timestamp >= :from "
+ + "&& timestamp <= :to "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="findByTargetAndTimestampAfter", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE targetStr == :targetStr "
+ + "&& timestamp >= :from "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="findByTargetAndTimestampBefore", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE targetStr == :targetStr "
+ + "&& timestamp <= :to "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="findByTarget", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE targetStr == :targetStr "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="findByTimestampBetween", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE timestamp >= :from "
+ + "&& timestamp <= :to "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="findByTimestampAfter", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE timestamp >= :from "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="findByTimestampBefore", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "WHERE timestamp <= :to "
+ + "ORDER BY timestamp DESC"),
+ @javax.jdo.annotations.Query(
+ name="find", language="JDOQL",
+ value="SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo "
+ + "ORDER BY timestamp DESC")
+})
+@MemberGroupLayout(
+ columnSpans={6,0,6},
+ left={"Identifiers","Target"},
+ right={"Detail","State"})
+@Immutable
+@Named("Published Event")
+@ObjectType("IsisPublishedEvent")
+public class PublishedEventJdo extends DomainChangeJdoAbstract implements HasTransactionId {
+
+ public static enum State {
+ QUEUED, PROCESSED
+ }
+
+ // //////////////////////////////////////
+
+ public PublishedEventJdo() {
+ super(ChangeType.PUBLISHED_EVENT);
+ }
+
+
+ // //////////////////////////////////////
+ // Identification
+ // //////////////////////////////////////
+
+ public String title() {
+ final TitleBuffer buf = new TitleBuffer();
+ buf.append(getEventType().name()).append(" ").append(getTargetStr());
+ if(getEventType()==EventType.ACTION_INVOCATION) {
+ buf.append(" ").append(getMemberIdentifier());
+ }
+ buf.append(",").append(getState());
+ return buf.toString();
+ }
+
+
+ // //////////////////////////////////////
+ // user (property)
+ // //////////////////////////////////////
+
+ private String user;
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=50)
+ @MemberOrder(name="Identifiers", sequence = "10")
+ @Hidden(where=Where.PARENTED_TABLES)
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(final String user) {
+ this.user = user;
+ }
+
+
+ // //////////////////////////////////////
+ // timestamp (property)
+ // //////////////////////////////////////
+
+ private java.sql.Timestamp timestamp;
+
+ @javax.jdo.annotations.Persistent
+ @javax.jdo.annotations.Column(allowsNull="false")
+ @MemberOrder(name="Identifiers", sequence = "20")
+ @Hidden(where=Where.PARENTED_TABLES)
+ public java.sql.Timestamp getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(final java.sql.Timestamp timestamp) {
+ this.timestamp = timestamp;
+ }
+
+
+
+ // //////////////////////////////////////
+ // transactionId
+ // //////////////////////////////////////
+
+ private UUID transactionId;
+
+ /**
+ * The unique identifier (a GUID) of the transaction in which this published event was persisted.
+ *
+ * <p>
+ * The combination of ({@link #getTransactionId() transactionId}, {@link #getSequence() sequence}) makes up the
+ * primary key.
+ */
+ @javax.jdo.annotations.PrimaryKey
+ @javax.jdo.annotations.Column(allowsNull="false",length=JdoColumnLength.TRANSACTION_ID)
+ @MemberOrder(name="Identifiers", sequence = "30")
+ @Hidden(where=Where.PARENTED_TABLES)
+ @Override
+ public UUID getTransactionId() {
+ return transactionId;
+ }
+
+ @Override
+ public void setTransactionId(final UUID transactionId) {
+ this.transactionId = transactionId;
+ }
+
+
+ // //////////////////////////////////////
+ // sequence
+ // //////////////////////////////////////
+
+ private int sequence;
+
+ /**
+ * The 0-based additional identifier of a published event within the given {@link #getTransactionId() transaction}.
+ *
+ * <p>
+ * The combination of ({@link #getTransactionId() transactionId}, {@link #getSequence() sequence}) makes up the
+ * primary key.
+ */
+ @javax.jdo.annotations.PrimaryKey
+ @MemberOrder(name="Identifiers", sequence = "40")
+ public int getSequence() {
+ return sequence;
+ }
+
+ public void setSequence(final int sequence) {
+ this.sequence = sequence;
+ }
+
+
+ // //////////////////////////////////////
+ // title
+ // //////////////////////////////////////
+
+ private String title;
+
+ /**
+ * Consists of the full oidStr (with version info etc), concatenated
+ * (if an {@link EventType#ACTION_INVOCATION}) with the name/parms of the action.
+ *
+ * <p>
+ * @deprecated - the oid of the target is also available (without the version info) through {@link #getTarget()}, and
+ * the action identifier is available through {@link #getMemberIdentifier()}.
+ */
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.PublishedEvent.TITLE)
+ @Hidden
+ @Deprecated
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+
+ // //////////////////////////////////////
+ // eventType (property)
+ // //////////////////////////////////////
+
+ private EventType eventType;
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.PublishedEvent.EVENT_TYPE)
+ @MemberOrder(name="Identifiers",sequence = "50")
+ public EventType getEventType() {
+ return eventType;
+ }
+
+ public void setEventType(final EventType eventType) {
+ this.eventType = eventType;
+ }
+
+
+ // //////////////////////////////////////
+ // targetClass (property)
+ // //////////////////////////////////////
+
+ private String targetClass;
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.TARGET_CLASS)
+ @TypicalLength(30)
+ @MemberOrder(name="Target", sequence = "10")
+ @Named("Class")
+ public String getTargetClass() {
+ return targetClass;
+ }
+
+ public void setTargetClass(final String targetClass) {
+ this.targetClass = Util.abbreviated(targetClass, JdoColumnLength.TARGET_CLASS);
+ }
+
+
+ // //////////////////////////////////////
+ // targetAction (property)
+ // //////////////////////////////////////
+
+ private String targetAction;
+
+ /**
+ * Only populated for {@link EventType#ACTION_INVOCATION}
+ */
+ @javax.jdo.annotations.Column(allowsNull="true", length=JdoColumnLength.TARGET_ACTION)
+ @TypicalLength(30)
+ @MemberOrder(name="Target", sequence = "20")
+ @Named("Action")
+ public String getTargetAction() {
+ return targetAction;
+ }
+
+ public void setTargetAction(final String targetAction) {
+ this.targetAction = Util.abbreviated(targetAction, JdoColumnLength.TARGET_ACTION);
+ }
+
+
+ // //////////////////////////////////////
+ // target (property)
+ // openTargetObject (action)
+ // //////////////////////////////////////
+
+
+ private String targetStr;
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.BOOKMARK, name="target")
+ @MemberOrder(name="Target", sequence="30")
+ @Named("Object")
+ public String getTargetStr() {
+ return targetStr;
+ }
+
+ public void setTargetStr(final String targetStr) {
+ this.targetStr = targetStr;
+ }
+
+
+ // //////////////////////////////////////
+ // memberIdentifier (property)
+ // //////////////////////////////////////
+
+ private String memberIdentifier;
+
+ /**
+ * Holds a string representation of the invoked action, equivalent to
+ * {@link Identifier#toClassAndNameIdentityString()}.
+ *
+ * <p>
+ * Only populated for {@link EventType#ACTION_INVOCATION},
+ * returns <tt>null</tt> otherwise.
+ *
+ * <p>
+ * This property is called 'memberIdentifier' rather than 'actionIdentifier' for
+ * consistency with other services (such as auditing and publishing) that may act on
+ * properties rather than simply just actions.
+ */
+ @javax.jdo.annotations.Column(allowsNull="true", length=JdoColumnLength.MEMBER_IDENTIFIER)
+ @TypicalLength(60)
+ @Hidden(where=Where.ALL_TABLES)
+ @MemberOrder(name="Detail",sequence = "20")
+ public String getMemberIdentifier() {
+ return memberIdentifier;
+ }
+
+ public void setMemberIdentifier(final String actionIdentifier) {
+ this.memberIdentifier = Util.abbreviated(actionIdentifier, JdoColumnLength.MEMBER_IDENTIFIER);
+ }
+
+
+
+ // //////////////////////////////////////
+ // state (property)
+ // //////////////////////////////////////
+
+ private State state;
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.PublishedEvent.STATE)
+ @MemberOrder(name="State", sequence = "30")
+ public State getState() {
+ return state;
+ }
+
+ public void setState(final State state) {
+ this.state = state;
+ }
+ private PublishedEventJdo setStateAndReturn(State state) {
+ setState(state);
+ return this;
+ }
+
+
+ // //////////////////////////////////////
+ // serializedFormZipped (property)
+ // serializedForm (derived property)
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.NotPersistent
+ @NotPersisted
+ @MultiLine(numberOfLines=14)
+ @Hidden(where=Where.ALL_TABLES)
+ @MemberOrder(name="Detail", sequence = "40")
+ public String getSerializedForm() {
+ byte[] zipped = getSerializedFormZipped();
+ if(zipped != null) {
+ return PublishingServiceJdo.fromZippedBytes(zipped);
+ } else {
+ return getSerializedFormClob();
+ }
+ }
+
+
+ // //////////////////////////////////////
+
+ @Deprecated
+ @javax.jdo.annotations.Column(allowsNull="true")
+ private byte[] serializedFormZipped;
+
+ @Deprecated
+ @Programmatic // ignored by Isis
+ public byte[] getSerializedFormZipped() {
+ return serializedFormZipped;
+ }
+
+ @Deprecated
+ public void setSerializedFormZipped(final byte[] serializedFormZipped) {
+ this.serializedFormZipped = serializedFormZipped;
+ }
+
+ // //////////////////////////////////////
+
+ private String serializedFormClob;
+
+ @Programmatic // ignored by Isis
+ @javax.jdo.annotations.Column(allowsNull="true", jdbcType="CLOB")
+ public String getSerializedFormClob() {
+ return serializedFormClob;
+ }
+
+ public void setSerializedFormClob(final String serializedFormClob) {
+ this.serializedFormClob = serializedFormClob;
+ }
+
+
+ // //////////////////////////////////////
+ // processed (action)
+ // reQueue (action)
+ // delete (action)
+ // //////////////////////////////////////
+
+
+ @Bulk
+ @ActionSemantics(Of.IDEMPOTENT)
+ @MemberOrder( name="State", sequence="10")
+ public PublishedEventJdo processed() {
+ return setStateAndReturn(State.PROCESSED);
+ }
+
+
+ @Bulk
+ @ActionSemantics(Of.IDEMPOTENT)
+ @MemberOrder(name="State", sequence="11")
+ public PublishedEventJdo reQueue() {
+ return setStateAndReturn(State.QUEUED);
+ }
+
+ @Bulk
+ @MemberOrder(name="State", sequence="12")
+ public void delete() {
+ container.removeIfNotAlready(this);
+ }
+
+
+
+ // //////////////////////////////////////
+ // toString
+ // //////////////////////////////////////
+
+ @Override
+ public String toString() {
+ return ObjectContracts.toString(this, "targetStr,timestamp,user,eventType,memberIdentifier,state");
+ }
+
+
+ // //////////////////////////////////////
+ // dependencies
+ // //////////////////////////////////////
+
+ @javax.inject.Inject
+ private BookmarkService bookmarkService;
+
+ @javax.inject.Inject
+ private DomainObjectContainer container;
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java
new file mode 100644
index 0000000..0666ed3
--- /dev/null
+++ b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishedEventJdoPK.java
@@ -0,0 +1,102 @@
+/*
+ * 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.objectstore.jdo.applib.service.publish;
+
+import java.io.Serializable;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+public class PublishedEventJdoPK implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String SEPARATOR = "_";
+
+ public UUID transactionId;
+ public int sequence;
+
+ // //////////////////////////////////////
+
+
+ public PublishedEventJdoPK() {
+ }
+
+ public PublishedEventJdoPK(final String value) {
+ final StringTokenizer token = new StringTokenizer (value, SEPARATOR);
+ this.transactionId = UUID.fromString(token.nextToken());
+ this.sequence = Integer.parseInt(token.nextToken());
+ }
+
+ // //////////////////////////////////////
+
+ public UUID getTransactionId() {
+ return transactionId;
+ }
+ public void setTransactionId(UUID transactionId) {
+ this.transactionId = transactionId;
+ }
+
+ // //////////////////////////////////////
+
+ public int getSequence() {
+ return sequence;
+ }
+ public void setSequence(int sequence) {
+ this.sequence = sequence;
+ }
+
+ // //////////////////////////////////////
+
+
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + sequence;
+ result = prime * result + ((transactionId == null) ? 0 : transactionId.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PublishedEventJdoPK other = (PublishedEventJdoPK) obj;
+ if (sequence != other.sequence)
+ return false;
+ if (transactionId == null) {
+ if (other.transactionId != null)
+ return false;
+ } else if (!transactionId.equals(other.transactionId))
+ return false;
+ return true;
+ }
+
+ // //////////////////////////////////////
+
+
+ @Override
+ public String toString() {
+ return transactionId + SEPARATOR + sequence;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
new file mode 100644
index 0000000..52903c8
--- /dev/null
+++ b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdo.java
@@ -0,0 +1,122 @@
+/*
+ * 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.objectstore.jdo.applib.service.publish;
+
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.publish.EventMetadata;
+import org.apache.isis.applib.services.publish.EventPayload;
+import org.apache.isis.applib.services.publish.EventSerializer;
+import org.apache.isis.applib.services.publish.PublishingService;
+
+/**
+ * An implementation of {@link PublishingService} that persists events as
+ * entities into a JDO-backed database.
+ */
+public class PublishingServiceJdo extends AbstractService implements PublishingService {
+
+ private static final String SERIALIZED_FORM_LOCAL_KEY = "datanucleus.PublishingService.serializedForm";
+ private final static String SERIALIZED_FORM_KEY = "isis.persistor." + SERIALIZED_FORM_LOCAL_KEY;
+
+ static enum SerializedForm {
+ CLOB,
+ @Deprecated
+ ZIPPED;
+ static SerializedForm parse(final String value) {
+ return CLOB.toString().equalsIgnoreCase(value)? CLOB: ZIPPED;
+ }
+ }
+
+ private SerializedForm serializedForm;
+
+ @Programmatic
+ @PostConstruct
+ public void init(Map<String,String> configuration) {
+ ensureDependenciesInjected();
+ serializedForm = SerializedForm.parse(configuration.get(SERIALIZED_FORM_KEY));
+ }
+
+
+ // //////////////////////////////////////
+
+ private void ensureDependenciesInjected() {
+ if(this.commandContext == null) {
+ throw new IllegalStateException(this.getClassName() + " requires CommandContext service to be configured");
+ }
+ if(this.eventSerializer == null) {
+ throw new IllegalStateException(this.getClassName() + " requires EventSerializer service to be configured");
+ }
+ }
+
+
+ @Override
+ @Programmatic
+ public void publish(final EventMetadata metadata, final EventPayload payload) {
+ final String serializedEvent = eventSerializer.serialize(metadata, payload).toString();
+ final PublishedEventJdo publishedEvent = newTransientInstance(PublishedEventJdo.class);
+
+ if(this.serializedForm == SerializedForm.ZIPPED) {
+ final byte[] zippedBytes = asZippedBytes(serializedEvent);
+ publishedEvent.setSerializedFormZipped(zippedBytes);
+ } else {
+ publishedEvent.setSerializedFormClob(serializedEvent);
+ }
+
+ publishedEvent.setTransactionId(metadata.getTransactionId());
+ publishedEvent.setSequence(metadata.getSequence());
+ publishedEvent.setEventType(metadata.getEventType());
+ publishedEvent.setTimestamp(metadata.getJavaSqlTimestamp());
+ publishedEvent.setUser(metadata.getUser());
+ publishedEvent.setTitle(metadata.getTitle());
+
+ publishedEvent.setTargetClass(metadata.getTargetClass());
+ publishedEvent.setTarget(metadata.getTarget());
+ publishedEvent.setTargetAction(metadata.getTargetAction());
+ publishedEvent.setMemberIdentifier(metadata.getActionIdentifier());
+
+ persist(publishedEvent);
+ }
+
+
+ static byte[] asZippedBytes(final String serializedEvent) {
+ return IoUtils.toUtf8ZippedBytes("serializedForm", serializedEvent);
+ }
+
+
+ // //////////////////////////////////////
+
+ private EventSerializer eventSerializer;
+
+ @Override
+ public void setEventSerializer(EventSerializer eventSerializer) {
+ this.eventSerializer = eventSerializer;
+ }
+
+ static String fromZippedBytes(byte[] zipped) {
+ return IoUtils.fromUtf8ZippedBytes("serializedForm", zipped);
+ }
+
+
+ @javax.inject.Inject
+ private CommandContext commandContext;
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.java
new file mode 100644
index 0000000..1709f64
--- /dev/null
+++ b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoContributions.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.objectstore.jdo.applib.service.publish;
+
+import java.util.List;
+
+import org.apache.isis.applib.AbstractFactoryAndRepository;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.Render;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.applib.annotation.NotContributed.As;
+import org.apache.isis.applib.annotation.Render.Type;
+import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.applib.services.HasTransactionId;
+
+
+public class PublishingServiceJdoContributions extends AbstractFactoryAndRepository {
+
+ @ActionSemantics(Of.SAFE)
+ @NotInServiceMenu
+ @NotContributed(As.ACTION)
+ @Render(Type.EAGERLY)
+ public List<PublishedEventJdo> publishedEvents(final HasTransactionId hasTransactionId) {
+ return publishedEventRepository.findByTransactionId(hasTransactionId.getTransactionId());
+ }
+
+ // //////////////////////////////////////
+
+ @javax.inject.Inject
+ private PublishingServiceJdoRepository publishedEventRepository;
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java
new file mode 100644
index 0000000..636369d
--- /dev/null
+++ b/core/module-publishing-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/PublishingServiceJdoRepository.java
@@ -0,0 +1,156 @@
+/*
+ * 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.objectstore.jdo.applib.service.publish;
+
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.UUID;
+import org.joda.time.LocalDate;
+import org.apache.isis.applib.AbstractFactoryAndRepository;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+
+/**
+ * Provides supporting functionality for querying and persisting
+ * {@link org.apache.isis.objectstore.jdo.applib.service.publish.PublishedEventJdo published event} entities.
+ *
+ * <p>
+ * This supporting service with no UI and no side-effects, and is there are no other implementations of the service,
+ * thus has been annotated with {@link org.apache.isis.applib.annotation.DomainService}. This means that there is no
+ * need to explicitly register it as a service (eg in <tt>isis.properties</tt>).
+ */
+@DomainService
+public class PublishingServiceJdoRepository extends AbstractFactoryAndRepository {
+
+ @Programmatic
+ public List<PublishedEventJdo> findQueued() {
+ return allMatches(
+ new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByStateOrderByTimestamp",
+ "state", PublishedEventJdo.State.QUEUED));
+ }
+
+ @Programmatic
+ public List<PublishedEventJdo> findProcessed() {
+ return allMatches(
+ new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByStateOrderByTimestamp",
+ "state", PublishedEventJdo.State.PROCESSED));
+ }
+
+ @Programmatic
+ public List<PublishedEventJdo> findByTransactionId(final UUID transactionId) {
+ return allMatches(
+ new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTransactionId",
+ "transactionId", transactionId));
+ }
+
+ @Programmatic
+ public void purgeProcessed() {
+ // REVIEW: this is not particularly performant.
+ // much better would be to go direct to the JDO API.
+ List<PublishedEventJdo> processedEvents = findProcessed();
+ for (PublishedEventJdo publishedEvent : processedEvents) {
+ publishedEvent.delete();
+ }
+ }
+
+
+ @Programmatic
+ public List<PublishedEventJdo> findByTargetAndFromAndTo(
+ final Bookmark target,
+ final LocalDate from,
+ final LocalDate to) {
+ final String targetStr = target.toString();
+ final Timestamp fromTs = toTimestampStartOfDayWithOffset(from, 0);
+ final Timestamp toTs = toTimestampStartOfDayWithOffset(to, 1);
+
+ final Query<PublishedEventJdo> query;
+ if(from != null) {
+ if(to != null) {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTargetAndTimestampBetween",
+ "targetStr", targetStr,
+ "from", fromTs,
+ "to", toTs);
+ } else {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTargetAndTimestampAfter",
+ "targetStr", targetStr,
+ "from", fromTs);
+ }
+ } else {
+ if(to != null) {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTargetAndTimestampBefore",
+ "targetStr", targetStr,
+ "to", toTs);
+ } else {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTarget",
+ "targetStr", targetStr);
+ }
+ }
+ return allMatches(query);
+ }
+
+ @Programmatic
+ public List<PublishedEventJdo> findByFromAndTo(
+ final LocalDate from,
+ final LocalDate to) {
+ final Timestamp fromTs = toTimestampStartOfDayWithOffset(from, 0);
+ final Timestamp toTs = toTimestampStartOfDayWithOffset(to, 1);
+
+ final Query<PublishedEventJdo> query;
+ if(from != null) {
+ if(to != null) {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTimestampBetween",
+ "from", fromTs,
+ "to", toTs);
+ } else {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTimestampAfter",
+ "from", fromTs);
+ }
+ } else {
+ if(to != null) {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "findByTimestampBefore",
+ "to", toTs);
+ } else {
+ query = new QueryDefault<PublishedEventJdo>(PublishedEventJdo.class,
+ "find");
+ }
+ }
+ return allMatches(query);
+ }
+
+ private static Timestamp toTimestampStartOfDayWithOffset(final LocalDate dt, int daysOffset) {
+ return dt!=null
+ ?new java.sql.Timestamp(dt.toDateTimeAtStartOfDay().plusDays(daysOffset).getMillis())
+ :null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/main/resources/images/PublishedEventJdo.png
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/main/resources/images/PublishedEventJdo.png b/core/module-publishing-jdo/src/main/resources/images/PublishedEventJdo.png
new file mode 100644
index 0000000..cb3a325
Binary files /dev/null and b/core/module-publishing-jdo/src/main/resources/images/PublishedEventJdo.png differ
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishing-jdo/src/test/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/module-publishing-jdo/src/test/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtilsTest.java b/core/module-publishing-jdo/src/test/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtilsTest.java
new file mode 100644
index 0000000..32cfde0
--- /dev/null
+++ b/core/module-publishing-jdo/src/test/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtilsTest.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.objectstore.jdo.applib.service.publish;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class IoUtilsTest {
+
+ @Test
+ public void roundtrip() {
+ final String str = "3784y5hrfbdgkjh3qyri f£$%$YTRGFDGER$£\"Eu098987u'!\"£%^&*IO(LUKJM)";
+ final byte[] utf8ZippedBytes = IoUtils.toUtf8ZippedBytes("serializedForm", str);
+
+ final String str2 = IoUtils.fromUtf8ZippedBytes("serializedForm", utf8ZippedBytes);
+
+ assertThat(str, (is(str2)));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishingeventserializer-ro/pom.xml
----------------------------------------------------------------------
diff --git a/core/module-publishingeventserializer-ro/pom.xml b/core/module-publishingeventserializer-ro/pom.xml
new file mode 100644
index 0000000..3feadb5
--- /dev/null
+++ b/core/module-publishingeventserializer-ro/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.apache.isis.module</groupId>
+ <artifactId>isis-module-publishingeventserializer-ro</artifactId>
+
+ <name>Isis Module: Publishing Event Servializer (Restful Objects spec)</name>
+ <description>
+ Implementation of an event serializer (as required by the publishing
+ service) that serialized the object as a JSON representation defined
+ by the Restful Objects spec.
+ </description>
+
+ <properties>
+ <siteBaseDir>..</siteBaseDir>
+ <relativeUrl>module-publishingeventserializer-ro/</relativeUrl>
+ </properties>
+
+ <url>http://isis.apache.org/${relativeUrl}</url>
+
+ <build>
+ <resources>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-applib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-viewer-restfulobjects-rendering</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-unittestsupport</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
----------------------------------------------------------------------
diff --git a/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java b/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
new file mode 100644
index 0000000..6d10cc2
--- /dev/null
+++ b/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/EventSerializerRendererContext.java
@@ -0,0 +1,95 @@
+/*
+ * 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.viewer.restfulobjects.rendering.eventserializer;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import com.google.common.collect.Sets;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+
+class EventSerializerRendererContext implements RendererContext {
+
+ private final String baseUrl;
+ private final Where where;
+
+ public EventSerializerRendererContext(String baseUrl, Where where) {
+ this.baseUrl = baseUrl;
+ this.where = where;
+ }
+
+ @Override
+ public String urlFor(String url) {
+ return baseUrl + url;
+ }
+
+ @Override
+ public AuthenticationSession getAuthenticationSession() {
+ return IsisContext.getAuthenticationSession();
+ }
+
+ @Override
+ public PersistenceSession getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+ @Override
+ public IsisConfiguration getConfiguration() {
+ return IsisContext.getConfiguration();
+ }
+
+ @Override
+ public AdapterManager getAdapterManager() {
+ return getPersistenceSession().getAdapterManager();
+ }
+
+ @Override
+ public List<List<String>> getFollowLinks() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Where getWhere() {
+ return where;
+ }
+
+ @Override
+ public Localization getLocalization() {
+ return IsisContext.getLocalization();
+ }
+
+ private Set<Oid> rendered = Sets.newHashSet();
+ @Override
+ public boolean canEagerlyRender(ObjectAdapter objectAdapter) {
+ final Oid oid = objectAdapter.getOid();
+ return rendered.add(oid);
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
----------------------------------------------------------------------
diff --git a/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java b/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
new file mode 100644
index 0000000..a95a934
--- /dev/null
+++ b/core/module-publishingeventserializer-ro/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/eventserializer/RestfulObjectsSpecEventSerializer.java
@@ -0,0 +1,124 @@
+/*
+ * 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.viewer.restfulobjects.rendering.eventserializer;
+
+import java.io.IOException;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.publish.EventMetadata;
+import org.apache.isis.applib.services.publish.EventPayload;
+import org.apache.isis.applib.services.publish.EventSerializer;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainObjectReprRenderer;
+
+/**
+ * Serializes {@link org.apache.isis.applib.services.publish.EventMetadata event metadata} and corresponding
+ * {@link org.apache.isis.applib.services.publish.EventPayload payload} into a JSON format corresponding to the
+ * domain object representation specified by the Restful Objects spec.
+ *
+ * <p>
+ * This implementation has no UI, has no side-effects, and there are no other implementations of the service API, and
+ * so it annotated with {@link org.apache.isis.applib.annotation.DomainService}. This class is implemented in the
+ * <tt>o.a.i.module:isis-module-publishingeventserializer-ro</tt> module. If that module is included in the classpath,
+ * it this means that this service is automatically registered; no further configuration is required.
+ */
+@DomainService
+public class RestfulObjectsSpecEventSerializer implements EventSerializer {
+
+ private final static String BASE_URL_KEY = "isis.viewer.restfulobjects.RestfulObjectsSpecEventSerializer.baseUrl";
+ private static final String BASE_URL_DEFAULT = "http://localhost:8080/restful/";
+
+ //region > init, shutdown
+ private String baseUrl;
+
+ @PostConstruct
+ public void init(Map<String,String> props) {
+ final String baseUrlFromConfig = props.get(BASE_URL_KEY);
+ baseUrl = baseUrlFromConfig != null? baseUrlFromConfig: BASE_URL_DEFAULT;
+ }
+
+ @PreDestroy
+ public void shutdown() {
+ }
+ //endregion
+
+ //region > serialize (API)
+ @Programmatic
+ @Override
+ public Object serialize(EventMetadata metadata, EventPayload payload) {
+ final RendererContext rendererContext = new EventSerializerRendererContext(baseUrl, Where.OBJECT_FORMS);
+
+ final JsonRepresentation payloadRepr = asPayloadRepr(rendererContext, payload);
+ final JsonRepresentation eventRepr = asEventRepr(metadata, payloadRepr);
+
+ return jsonFor(eventRepr);
+ }
+ //endregion
+
+ //region > supporting methods
+ JsonRepresentation asEventRepr(EventMetadata metadata, final JsonRepresentation payloadRepr) {
+ final JsonRepresentation eventRepr = JsonRepresentation.newMap();
+ final JsonRepresentation metadataRepr = JsonRepresentation.newMap();
+ eventRepr.mapPut("metadata", metadataRepr);
+ metadataRepr.mapPut("id", metadata.getId());
+ metadataRepr.mapPut("transactionId", metadata.getTransactionId());
+ metadataRepr.mapPut("sequence", metadata.getSequence());
+ metadataRepr.mapPut("eventType", metadata.getEventType());
+ metadataRepr.mapPut("user", metadata.getUser());
+ metadataRepr.mapPut("timestamp", metadata.getTimestamp());
+ eventRepr.mapPut("payload", payloadRepr);
+ return eventRepr;
+ }
+
+ JsonRepresentation asPayloadRepr(final RendererContext rendererContext, EventPayload payload) {
+ final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(rendererContext, null, JsonRepresentation.newMap());
+ final ObjectAdapter objectAdapter = rendererContext.getAdapterManager().adapterFor(payload);
+ renderer.with(objectAdapter).asEventSerialization();
+ return renderer.render();
+ }
+
+ String jsonFor(final Object object) {
+ try {
+ return getJsonMapper().write(object);
+ } catch (final JsonGenerationException e) {
+ throw new RuntimeException(e);
+ } catch (final JsonMappingException e) {
+ throw new RuntimeException(e);
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final static JsonMapper jsonMapper = JsonMapper.instance();
+
+ JsonMapper getJsonMapper() {
+ return jsonMapper;
+ }
+ //endregion
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-publishingeventserializer-ro/src/main/resources/images/PublishedEventJdo.png
----------------------------------------------------------------------
diff --git a/core/module-publishingeventserializer-ro/src/main/resources/images/PublishedEventJdo.png b/core/module-publishingeventserializer-ro/src/main/resources/images/PublishedEventJdo.png
new file mode 100644
index 0000000..cb3a325
Binary files /dev/null and b/core/module-publishingeventserializer-ro/src/main/resources/images/PublishedEventJdo.png differ
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
new file mode 100644
index 0000000..22d5e77
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingJdo.java
@@ -0,0 +1,96 @@
+/*
+ * 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.objectstore.jdo.applib.service.settings;
+
+import javax.jdo.annotations.IdentityType;
+
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.services.settings.ApplicationSetting;
+import org.apache.isis.applib.services.settings.SettingType;
+import org.apache.isis.objectstore.jdo.applib.service.JdoColumnLength;
+
+@javax.jdo.annotations.PersistenceCapable(
+ identityType = IdentityType.APPLICATION,
+ table="IsisApplicationSetting")
+@javax.jdo.annotations.Queries({
+ @javax.jdo.annotations.Query(
+ name = "findByKey", language = "JDOQL",
+ value = "SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.settings.ApplicationSettingJdo "
+ + "WHERE key == :key"),
+ @javax.jdo.annotations.Query(
+ name = "findAll", language = "JDOQL",
+ value = "SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.settings.ApplicationSettingJdo "
+ + "ORDER BY key")
+})
+@Named("Application Setting")
+public class ApplicationSettingJdo extends SettingAbstractJdo implements ApplicationSetting {
+
+
+ @javax.jdo.annotations.Column(length=JdoColumnLength.SettingAbstract.SETTING_KEY)
+ @javax.jdo.annotations.PrimaryKey
+ public String getKey() {
+ return super.getKey();
+ }
+ @Override
+ public void setKey(String key) {
+ super.setKey(key);
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(length=JdoColumnLength.DESCRIPTION)
+ @javax.jdo.annotations.Persistent
+ @Override
+ public String getDescription() {
+ return super.getDescription();
+ }
+ @Override
+ public void setDescription(String description) {
+ super.setDescription(description);
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.VALUE_RAW)
+ @javax.jdo.annotations.Persistent
+ @Override
+ public String getValueRaw() {
+ return super.getValueRaw();
+ }
+ @Override
+ public void setValueRaw(String valueAsRaw) {
+ super.setValueRaw(valueAsRaw);
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.SETTING_TYPE)
+ @javax.jdo.annotations.Persistent
+ @Override
+ public SettingType getType() {
+ return super.getType();
+ }
+ @Override
+ public void setType(SettingType type) {
+ super.setType(type);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
new file mode 100644
index 0000000..014455a
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdo.java
@@ -0,0 +1,120 @@
+/*
+ * 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.objectstore.jdo.applib.service.settings;
+
+import java.util.List;
+
+import org.joda.time.LocalDate;
+
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.Optional;
+import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.applib.services.settings.ApplicationSetting;
+import org.apache.isis.applib.services.settings.ApplicationSettingsService;
+import org.apache.isis.applib.services.settings.ApplicationSettingsServiceRW;
+import org.apache.isis.applib.services.settings.SettingAbstract;
+import org.apache.isis.applib.services.settings.SettingType;
+
+/**
+ * An implementation of {@link ApplicationSettingsService} that persists settings
+ * as entities into a JDO-backed database.
+ */
+@Named("Application Settings")
+public class ApplicationSettingsServiceJdo extends AbstractService implements ApplicationSettingsServiceRW {
+
+ @ActionSemantics(Of.SAFE)
+ @Override
+ public ApplicationSetting find(@Named("Key") String key) {
+ return firstMatch(
+ new QueryDefault<ApplicationSettingJdo>(ApplicationSettingJdo.class,
+ "findByKey",
+ "key", key));
+ }
+
+ // //////////////////////////////////////
+
+ @ActionSemantics(Of.SAFE)
+ @MemberOrder(sequence="1")
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public List<ApplicationSetting> listAll() {
+ return (List)allMatches(
+ new QueryDefault<ApplicationSettingJdo>(ApplicationSettingJdo.class,
+ "findAll"));
+ }
+
+ // //////////////////////////////////////
+
+ @MemberOrder(sequence="10")
+ @Override
+ public ApplicationSetting newString(
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") String value) {
+ return newSetting(key, description, SettingType.STRING, value);
+ }
+ @MemberOrder(sequence="11")
+ @Override
+ public ApplicationSettingJdo newInt(
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") Integer value) {
+ return newSetting(key, description, SettingType.INT, value.toString());
+ }
+ @MemberOrder(sequence="12")
+ @Override
+ public ApplicationSettingJdo newLong(
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") Long value) {
+ return newSetting(key, description, SettingType.LONG, value.toString());
+ }
+ @MemberOrder(sequence="13")
+ @Override
+ public ApplicationSettingJdo newLocalDate(
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") LocalDate value) {
+ return newSetting(key, description, SettingType.LOCAL_DATE, value.toString(SettingAbstract.DATE_FORMATTER));
+ }
+ @MemberOrder(sequence="14")
+ @Override
+ public ApplicationSettingJdo newBoolean(
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") @Optional Boolean value) {
+ return newSetting(key, description, SettingType.BOOLEAN, new Boolean(value != null && value).toString());
+ }
+
+ private ApplicationSettingJdo newSetting(
+ String key, String description, SettingType settingType, final String valueRaw) {
+ final ApplicationSettingJdo setting = newTransientInstance(ApplicationSettingJdo.class);
+ setting.setKey(key);
+ setting.setDescription(description);
+ setting.setValueRaw(valueRaw);
+ setting.setType(settingType);
+ persist(setting);
+ return setting;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdoHidden.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdoHidden.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdoHidden.java
new file mode 100644
index 0000000..95512c0
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/ApplicationSettingsServiceJdoHidden.java
@@ -0,0 +1,81 @@
+/*
+ * 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.objectstore.jdo.applib.service.settings;
+
+import java.util.List;
+
+import org.joda.time.LocalDate;
+
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.services.settings.ApplicationSetting;
+
+/**
+ * An implementation intended to be hidden in the UI, and delegated to by other services.
+ */
+public class ApplicationSettingsServiceJdoHidden extends ApplicationSettingsServiceJdo {
+
+ @Hidden
+ @Override
+ public ApplicationSetting find(@Named("Key") String key) {
+ return super.find(key);
+ }
+
+ // //////////////////////////////////////
+
+ @Hidden
+ @Override
+ public List<ApplicationSetting> listAll() {
+ return super.listAll();
+ }
+
+ // //////////////////////////////////////
+
+ @Hidden
+ @Override
+ public ApplicationSetting newString(String key, String description, String value) {
+ return super.newString(key, description, value);
+ }
+
+ @Hidden
+ @Override
+ public ApplicationSettingJdo newInt(String key, String description, Integer value) {
+ return super.newInt(key, description, value);
+ }
+
+ @Hidden
+ @Override
+ public ApplicationSettingJdo newLong(String key, String description, Long value) {
+ return super.newLong(key, description, value);
+ }
+
+ @Hidden
+ @Override
+ public ApplicationSettingJdo newLocalDate(String key, String description, LocalDate value) {
+ return super.newLocalDate(key, description, value);
+ }
+
+ @Hidden
+ @Override
+ public ApplicationSettingJdo newBoolean(String key, String description, Boolean value) {
+ return super.newBoolean(key, description, value);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/SettingAbstractJdo.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/SettingAbstractJdo.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/SettingAbstractJdo.java
new file mode 100644
index 0000000..8e6f8da
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/SettingAbstractJdo.java
@@ -0,0 +1,190 @@
+/*
+ * 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.objectstore.jdo.applib.service.settings;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+import org.joda.time.LocalDate;
+
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.Optional;
+import org.apache.isis.applib.services.settings.SettingType;
+
+/**
+ * Factors out common implementation; however this is annotated with {@link PersistenceCapable},
+ * so that each subclass is its own root entity.
+ */
+public abstract class SettingAbstractJdo extends org.apache.isis.applib.services.settings.SettingAbstract implements org.apache.isis.applib.services.settings.ApplicationSetting {
+
+ private String key;
+
+ @javax.jdo.annotations.Column(allowsNull="false")
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ // //////////////////////////////////////
+
+ private String description;
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ @MemberOrder(name="Description", sequence="1")
+ @Named("Update")
+ public SettingAbstractJdo updateDescription(@Named("Description") @Optional String description) {
+ setDescription(description);
+ return this;
+ }
+ public String default0UpdateDescription() {
+ return getDescription();
+ }
+
+ // //////////////////////////////////////
+
+ private SettingType type;
+
+ @javax.jdo.annotations.Column(allowsNull="false")
+ public SettingType getType() {
+ return type;
+ }
+
+ public void setType(final SettingType type) {
+ this.type = type;
+ }
+
+ // //////////////////////////////////////
+
+ private String valueRaw;
+
+ @javax.jdo.annotations.Column(allowsNull="false")
+ public String getValueRaw() {
+ return valueRaw;
+ }
+
+ public void setValueRaw(final String valueAsRaw) {
+ this.valueRaw = valueAsRaw;
+ }
+
+ // //////////////////////////////////////
+
+ @MemberOrder(name="ValueAsString", sequence="1")
+ @Named("Update")
+ public SettingAbstractJdo updateAsString(@Named("Value") String value) {
+ setValueRaw(value);
+ return this;
+ }
+ public String default0UpdateAsString() {
+ return getValueAsString();
+ }
+ public boolean hideUpdateAsString() {
+ return typeIsNot(SettingType.STRING);
+ }
+
+ @MemberOrder(name="ValueAsInt", sequence="1")
+ @Named("Update")
+ public SettingAbstractJdo updateAsInt(@Named("Value") Integer value) {
+ setValueRaw(value.toString());
+ return this;
+ }
+ public Integer default0UpdateAsInt() {
+ return getValueAsInt();
+ }
+ public boolean hideUpdateAsInt() {
+ return typeIsNot(SettingType.INT);
+ }
+
+ @MemberOrder(name="ValueAsLong", sequence="1")
+ @Named("Update")
+ public SettingAbstractJdo updateAsLong(@Named("Value") Long value) {
+ setValueRaw(value.toString());
+ return this;
+ }
+ public Long default0UpdateAsLong() {
+ return getValueAsLong();
+ }
+ public boolean hideUpdateAsLong() {
+ return typeIsNot(SettingType.LONG);
+ }
+
+ @MemberOrder(name="ValueAsLocalDate", sequence="1")
+ @Named("Update")
+ public SettingAbstractJdo updateAsLocalDate(@Named("Value") LocalDate value) {
+ setValueRaw(value.toString(DATE_FORMATTER));
+ return this;
+ }
+ public LocalDate default0UpdateAsLocalDate() {
+ return getValueAsLocalDate();
+ }
+ public boolean hideUpdateAsLocalDate() {
+ return typeIsNot(SettingType.LOCAL_DATE);
+ }
+
+ @MemberOrder(name="ValueAsBoolean", sequence="1")
+ @Named("Update")
+ public SettingAbstractJdo updateAsBoolean(@Named("Value") Boolean value) {
+ setValueRaw(value.toString());
+ return this;
+ }
+ public Boolean default0UpdateAsBoolean() {
+ return getValueAsBoolean();
+ }
+ public boolean hideUpdateAsBoolean() {
+ return typeIsNot(SettingType.BOOLEAN);
+ }
+
+ // //////////////////////////////////////
+
+
+ public SettingAbstractJdo delete(
+ @Named("Are you sure?") @Optional Boolean confirm) {
+ if(confirm == null || !confirm) {
+ container.informUser("Setting NOT deleted");
+ return this;
+ }
+ container.remove(this);
+ container.informUser("Setting deleted");
+ return null;
+ }
+
+
+
+
+ // //////////////////////////////////////
+
+ private DomainObjectContainer container;
+
+ public void setDomainObjectContainer(final DomainObjectContainer container) {
+ this.container = container;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
new file mode 100644
index 0000000..f1ff4b2
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdo.java
@@ -0,0 +1,129 @@
+/*
+ * 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.objectstore.jdo.applib.service.settings;
+
+
+import javax.jdo.annotations.IdentityType;
+
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.Title;
+import org.apache.isis.applib.services.settings.SettingType;
+import org.apache.isis.applib.services.settings.UserSetting;
+import org.apache.isis.objectstore.jdo.applib.service.JdoColumnLength;
+
+@javax.jdo.annotations.PersistenceCapable(
+ identityType = IdentityType.APPLICATION,
+ objectIdClass=UserSettingJdoPK.class,
+ table="IsisUserSetting")
+@javax.jdo.annotations.Queries({
+ @javax.jdo.annotations.Query(
+ name = "findByUserAndKey", language = "JDOQL",
+ value = "SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.settings.UserSettingJdo "
+ + "WHERE user == :user "
+ + "&& key == :key ")
+ ,@javax.jdo.annotations.Query(
+ name = "findByUser", language = "JDOQL",
+ value = "SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.settings.UserSettingJdo "
+ + "WHERE user == :user "
+ + "ORDER BY key")
+ ,@javax.jdo.annotations.Query(
+ name = "findAll", language = "JDOQL",
+ value = "SELECT "
+ + "FROM org.apache.isis.objectstore.jdo.applib.service.settings.UserSettingJdo "
+ + "ORDER BY user, key")
+})
+// can't see how to specify this order in the primary key; however HSQLDB objects :-(
+//@javax.jdo.annotations.Unique(name="USER_KEY_IDX", members={"user","key"})
+@Named("User Setting")
+public class UserSettingJdo extends SettingAbstractJdo implements UserSetting {
+
+
+ private String user;
+
+ @javax.jdo.annotations.Column(length=JdoColumnLength.USER_NAME)
+ @javax.jdo.annotations.PrimaryKey
+ @Title(sequence="5", append=": ")
+ @MemberOrder(sequence = "5")
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(final String user) {
+ this.user = user;
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(length=JdoColumnLength.SettingAbstract.SETTING_KEY)
+ @javax.jdo.annotations.PrimaryKey
+ @Title(sequence="10")
+ @Override
+ public String getKey() {
+ return super.getKey();
+ }
+ @Override
+ public void setKey(String key) {
+ super.setKey(key);
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(length=JdoColumnLength.DESCRIPTION)
+ @javax.jdo.annotations.Persistent
+ @Override
+ public String getDescription() {
+ return super.getDescription();
+ }
+ @Override
+ public void setDescription(String description) {
+ super.setDescription(description);
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.VALUE_RAW)
+ @javax.jdo.annotations.Persistent
+ @Title(prepend=" = ", sequence="30")
+ @Override
+ public String getValueRaw() {
+ return super.getValueRaw();
+ }
+ @Override
+ public void setValueRaw(String valueAsRaw) {
+ super.setValueRaw(valueAsRaw);
+ }
+
+ // //////////////////////////////////////
+
+ @javax.jdo.annotations.Column(allowsNull="false", length=JdoColumnLength.SettingAbstract.SETTING_TYPE)
+ @javax.jdo.annotations.Persistent
+ @Override
+ public SettingType getType() {
+ return super.getType();
+ }
+ @Override
+ public void setType(SettingType type) {
+ super.setType(type);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java
new file mode 100644
index 0000000..13a20ed
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingJdoPK.java
@@ -0,0 +1,90 @@
+/**
+ * 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.objectstore.jdo.applib.service.settings;
+
+import java.io.Serializable;
+import java.util.StringTokenizer;
+
+/**
+ * @see http://www.datanucleus.org/products/datanucleus/jdo/primary_key.html
+ */
+public class UserSettingJdoPK implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+
+ public String user;
+ public String key;
+
+ public UserSettingJdoPK ()
+ {
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ public String getKey() {
+ return key;
+ }
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+
+ /**
+ * Constructor accepting same input as generated by toString().
+ */
+ public UserSettingJdoPK(String value)
+ {
+ StringTokenizer token = new StringTokenizer (value, ";;");
+ token.nextToken(); // className
+ this.setUser(token.nextToken()); // user
+ this.setKey(token.nextToken()); // key
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+ if (!(obj instanceof UserSettingJdoPK))
+ {
+ return false;
+ }
+ UserSettingJdoPK c = (UserSettingJdoPK)obj;
+
+ return getUser().equals(c.getUser()) && getKey().equals(c.getKey());
+ }
+
+ public int hashCode ()
+ {
+ return this.getUser().hashCode() ^ this.getKey().hashCode();
+ }
+
+ public String toString ()
+ {
+ // Give output expected by String constructor
+ return this.getClass().getName() + ";;" + this.getUser() + ";;" + this.getKey();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/e3c20592/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingsServiceJdo.java
----------------------------------------------------------------------
diff --git a/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingsServiceJdo.java b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingsServiceJdo.java
new file mode 100644
index 0000000..21ba8b9
--- /dev/null
+++ b/core/module-settings/impl-jdo/src/main/java/org/apache/isis/objectstore/jdo/applib/service/settings/UserSettingsServiceJdo.java
@@ -0,0 +1,170 @@
+/*
+ * 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.objectstore.jdo.applib.service.settings;
+
+import java.util.List;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import org.joda.time.LocalDate;
+
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.Optional;
+import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.applib.services.settings.SettingAbstract;
+import org.apache.isis.applib.services.settings.SettingType;
+import org.apache.isis.applib.services.settings.UserSetting;
+import org.apache.isis.applib.services.settings.UserSettingsService;
+import org.apache.isis.applib.services.settings.UserSettingsServiceRW;
+
+/**
+ * An implementation of {@link UserSettingsService} that persists settings
+ * as entities into a JDO-backed database.
+ */
+@Named("User Settings")
+public class UserSettingsServiceJdo extends AbstractService implements UserSettingsServiceRW {
+
+ @Override
+ public UserSetting find(
+ @Named("User") String user,
+ @Named("Key") String key) {
+ return firstMatch(
+ new QueryDefault<UserSettingJdo>(UserSettingJdo.class,
+ "findByUserAndKey",
+ "user",user,
+ "key", key));
+ }
+
+
+ // //////////////////////////////////////
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public List<UserSetting> listAllFor(String user) {
+ return (List)allMatches(
+ new QueryDefault<UserSettingJdo>(UserSettingJdo.class,
+ "findByUser",
+ "user", user));
+ }
+ public List<String> choices0ListAllFor() {
+ return existingUsers();
+ }
+
+ private List<String> existingUsers() {
+ final List<UserSetting> listAll = listAll();
+ return Lists.newArrayList(Sets.newTreeSet(Iterables.transform(listAll, GET_USER)));
+ }
+
+ private final static Function<UserSetting, String> GET_USER = new Function<UserSetting, String>() {
+ public String apply(UserSetting input) {
+ return input.getUser();
+ }
+ };
+
+ // //////////////////////////////////////
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public List<UserSetting> listAll() {
+ return (List)allMatches(
+ new QueryDefault<UserSettingJdo>(UserSettingJdo.class,
+ "findAll"));
+ }
+
+
+ // //////////////////////////////////////
+
+ @MemberOrder(sequence="10")
+ public UserSettingJdo newString(
+ @Named("User") String user,
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") String value) {
+ return newSetting(user, key, description, SettingType.STRING, value);
+ }
+ public String default0NewString() {
+ return getContainer().getUser().getName();
+ }
+
+ @MemberOrder(sequence="11")
+ public UserSettingJdo newInt(
+ @Named("User") String user,
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") Integer value) {
+ return newSetting(user, key, description, SettingType.INT, value.toString());
+ }
+ public String default0NewInt() {
+ return getContainer().getUser().getName();
+ }
+
+ @MemberOrder(sequence="12")
+ public UserSettingJdo newLong(
+ @Named("User") String user,
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") Long value) {
+ return newSetting(user, key, description, SettingType.LONG, value.toString());
+ }
+ public String default0NewLong() {
+ return getContainer().getUser().getName();
+ }
+
+ @MemberOrder(sequence="13")
+ public UserSettingJdo newLocalDate(
+ @Named("User") String user,
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") LocalDate value) {
+ return newSetting(user, key, description, SettingType.LOCAL_DATE, value.toString(SettingAbstract.DATE_FORMATTER));
+ }
+ public String default0NewLocalDate() {
+ return getContainer().getUser().getName();
+ }
+
+ @MemberOrder(sequence="14")
+ public UserSettingJdo newBoolean(
+ @Named("User") String user,
+ @Named("Key") String key,
+ @Named("Description") @Optional String description,
+ @Named("Value") @Optional Boolean value) {
+ return newSetting(user, key, description, SettingType.BOOLEAN, new Boolean(value != null && value).toString());
+ }
+ public String default0NewBoolean() {
+ return getContainer().getUser().getName();
+ }
+
+ private UserSettingJdo newSetting(
+ String user, String key, String description, SettingType settingType, final String valueRaw) {
+ final UserSettingJdo setting = newTransientInstance(UserSettingJdo.class);
+ setting.setUser(user);
+ setting.setKey(key);
+ setting.setType(settingType);
+ setting.setDescription(description);
+ setting.setValueRaw(valueRaw);
+ persist(setting);
+ return setting;
+ }
+
+
+}