diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmObject.java b/ccm-core/src/main/java/org/libreccm/core/CcmObject.java index 5db408bab..58ea15995 100644 --- a/ccm-core/src/main/java/org/libreccm/core/CcmObject.java +++ b/ccm-core/src/main/java/org/libreccm/core/CcmObject.java @@ -236,7 +236,7 @@ public class CcmObject implements Serializable { * also overwrite the {@link #canEqual(java.lang.Object)} method. * * A good pattern for implementing {@code equals(Object)} is the following - * (this is similar to {@code equals(Object) implemenation created by + * (this is similar to {@code equals(Object)} implemenation created by * Netbeans): * *
diff --git a/ccm-core/src/main/java/org/libreccm/notification/Digest.java b/ccm-core/src/main/java/org/libreccm/notification/Digest.java
new file mode 100644
index 000000000..c783ce6fb
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/notification/Digest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.notification;
+
+import org.libreccm.core.CcmObject;
+import org.libreccm.core.Party;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+/**
+ *
+ * Models the envelope information associated with a digest.
+ *
+ * When a digest is processed, all notifications associated with it are grouped
+ * for delivery as a single unit to each receiver. The outbound email generated
+ * for the receivers has a common subject, header, separator between the
+ * individual messages, and signature (from the documentation of the
+ * {@code com.arsdigita.notification.Digest} class).
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "digests")
+public class Digest extends CcmObject implements Serializable {
+
+ private static final long serialVersionUID = -3526066971290670390L;
+
+ @OneToOne
+ @JoinColumn(name = "from_party_id")
+ private Party fromParty;
+
+ @Column(name = "subject", length = 255, nullable = false)
+ private String subject;
+
+ @Column(name = "header", length = 4096, nullable = false)
+ private String header;
+
+ @Column(name = "separator", length = 128, nullable = false)
+ private String separator;
+
+ @Column(name = "signature", length = 4096, nullable = false)
+ private String signature;
+
+ @Column(name = "frequency")
+ private Integer frequency;
+
+ @Column(name = "next_run")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date nextRun;
+
+ public Party getFromParty() {
+ return fromParty;
+ }
+
+ public void setFromParty(final Party fromParty) {
+ this.fromParty = fromParty;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(final String subject) {
+ this.subject = subject;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void setHeader(final String header) {
+ this.header = header;
+ }
+
+ public String getSeparator() {
+ return separator;
+ }
+
+ public void setSeparator(final String separator) {
+ this.separator = separator;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public void setSignature(final String signature) {
+ this.signature = signature;
+ }
+
+ public Integer getFrequency() {
+ return frequency;
+ }
+
+ public void setFrequency(final Integer frequency) {
+ this.frequency = frequency;
+ }
+
+ public Date getNextRun() {
+ return new Date(nextRun.getTime());
+ }
+
+ public void setNextRun(final Date nextRun) {
+ this.nextRun = new Date(nextRun.getTime());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ hash = 37 * hash + Objects.hashCode(fromParty);
+ hash = 37 * hash + Objects.hashCode(subject);
+ hash = 37 * hash + Objects.hashCode(header);
+ hash = 37 * hash + Objects.hashCode(separator);
+ hash = 37 * hash + Objects.hashCode(signature);
+ hash = 37 * hash + Objects.hashCode(frequency);
+ hash = 37 * hash + Objects.hashCode(nextRun);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ if (!super.equals(obj)) {
+ return false;
+ }
+
+ final Digest other = (Digest) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+
+ if (!Objects.equals(fromParty, other.getFromParty())) {
+ return false;
+ }
+ if (!Objects.equals(subject, other.getSubject())) {
+ return false;
+ }
+ if (!Objects.equals(header, other.getHeader())) {
+ return false;
+ }
+ if (!Objects.equals(separator, other.getSeparator())) {
+ return false;
+ }
+ if (!Objects.equals(signature, other.getSignature())) {
+ return false;
+ }
+ if (!Objects.equals(frequency, other.getFrequency())) {
+ return false;
+ }
+ return Objects.equals(nextRun, other.getNextRun());
+ }
+
+ @Override
+ public boolean canEqual(final Object obj) {
+ return obj instanceof Digest;
+ }
+
+ @Override
+ public String toString(final String data) {
+ return super.toString(String.format(", fromParty = %s, "
+ + "subject = \"%s\", "
+ + "frequency = %d,"
+ + "nextRun = %tF %Email Alerts
+ *
+ * When using notifications for email alerts, applications often
+ * need to wrap a special header and signature around the contained
+ * Message object. This can be useful for including introductory
+ * remarks and action links in the email body. The
+ * {@code setHeader} and {@code setSignature} methods allow
+ * you to do this without the need to create a separate Message for
+ * the modified email.
+ * *
+ * Digests
+ *
+ * Finally, notifications can be sent in "instant processing mode"
+ * or as part of a {@link Digest}. When sent as part of a digest all
+ * notifications to the same recipient are collected into a single
+ * email and sent at regular internal. For example, an hourly digest
+ * might send a user all of their workflow task updates that have
+ * changed in the past hour, rather a much larger number of individual
+ * messages every time an tasks changed.
+ *
+ * (Documentation taken from the {@code com.arsdigita.notification.Notification}
+ * class)
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "notifications")
+public class Notification extends CcmObject implements Serializable {
+
+ private static final long serialVersionUID = -6052859580690813506L;
+
+ @OneToOne
+ @JoinColumn(name = "receiver_id")
+ private Party receiver;
+
+ @OneToOne
+ @JoinColumn(name = "digest_id")
+ private Digest digest;
+
+ @OneToOne
+ @JoinColumn(name = "message_id")
+ private Message message;
+
+ @Column(name = "header", length = 4096)
+ private String header;
+
+ @Column(name = "signature", length = 4096)
+ private String signature;
+
+ @Column(name = "expand_group")
+ private boolean expandGroup;
+
+ @Column(name = "request_date")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date requestDate;
+
+ @Column(name = "fulfill_date")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date fulfillDate;
+
+ @Column(name = "status", length = 32)
+ private String status;
+
+ @Column(name = "max_retries")
+ private long maxRetries;
+
+ @Column(name = "expunge")
+ private boolean expunge;
+
+ @Column(name = "expunge_message")
+ private boolean expungeMessage;
+
+ public Party getReceiver() {
+ return receiver;
+ }
+
+ public void setReceiver(final Party receiver) {
+ this.receiver = receiver;
+ }
+
+ public Digest getDigest() {
+ return digest;
+ }
+
+ public void setDigest(final Digest digest) {
+ this.digest = digest;
+ }
+
+ public Message getMessage() {
+ return message;
+ }
+
+ public void setMessage(final Message message) {
+ this.message = message;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void setHeader(final String header) {
+ this.header = header;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public void setSignature(final String signature) {
+ this.signature = signature;
+ }
+
+ public boolean isExpandGroup() {
+ return expandGroup;
+ }
+
+ public void setExpandGroup(final boolean expandGroup) {
+ this.expandGroup = expandGroup;
+ }
+
+ public Date getRequestDate() {
+ return new Date(requestDate.getTime());
+ }
+
+ public void setRequestDate(final Date requestDate) {
+ this.requestDate = new Date(requestDate.getTime());
+ }
+
+ public Date getFulfillDate() {
+ return new Date(fulfillDate.getTime());
+ }
+
+ public void setFulfillDate(final Date fulfillDate) {
+ this.fulfillDate = new Date(fulfillDate.getTime());
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(final String status) {
+ this.status = status;
+ }
+
+ public long getMaxRetries() {
+ return maxRetries;
+ }
+
+ public void setMaxRetries(final long maxRetries) {
+ this.maxRetries = maxRetries;
+ }
+
+ public boolean isExpunge() {
+ return expunge;
+ }
+
+ public void setExpunge(final boolean expunge) {
+ this.expunge = expunge;
+ }
+
+ public boolean isExpungeMessage() {
+ return expungeMessage;
+ }
+
+ public void setExpungeMessage(final boolean expungeMessage) {
+ this.expungeMessage = expungeMessage;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ hash = 53 * hash + Objects.hashCode(receiver);
+ hash = 53 * hash + Objects.hashCode(digest);
+ hash = 53 * hash + Objects.hashCode(message);
+ hash = 53 * hash + Objects.hashCode(header);
+ hash = 53 * hash + Objects.hashCode(signature);
+ hash = 53 * hash + (expandGroup ? 1 : 0);
+ hash = 53 * hash + Objects.hashCode(requestDate);
+ hash = 53 * hash + Objects.hashCode(fulfillDate);
+ hash = 53 * hash + Objects.hashCode(status);
+ hash = 53 * hash + (int) (maxRetries ^ (maxRetries >>> 32));
+ hash = 53 * hash + (expunge ? 1 : 0);
+ hash = 53 * hash + (expungeMessage ? 1 : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ if (!super.equals(obj)) {
+ return false;
+ }
+
+ final Notification other = (Notification) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+
+ if (!Objects.equals(receiver, other.getReceiver())) {
+ return false;
+ }
+ if (!Objects.equals(digest, other.getDigest())) {
+ return false;
+ }
+ if (!Objects.equals(message, other.getMessage())) {
+ return false;
+ }
+ if (!Objects.equals(header, other.getHeader())) {
+ return false;
+ }
+ if (!Objects.equals(signature, other.getSignature())) {
+ return false;
+ }
+ if (expandGroup != other.isExpandGroup()) {
+ return false;
+ }
+ if (!Objects.equals(requestDate, other.getRequestDate())) {
+ return false;
+ }
+ if (!Objects.equals(fulfillDate, other.getFulfillDate())) {
+ return false;
+ }
+ if (!Objects.equals(status, other.getStatus())) {
+ return false;
+ }
+ if (maxRetries != other.getMaxRetries()) {
+ return false;
+ }
+ if (expunge != other.isExpunge()) {
+ return false;
+ }
+ if (expungeMessage != other.isExpungeMessage()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean canEqual(final Object obj) {
+ return obj instanceof Notification;
+ }
+
+ @Override
+ public String toString(final String data) {
+ return super.toString(String.format(", receiver = %s, "
+ + "digest = %s, "
+ + "message = %s, "
+ + "expandGroup = %b, "
+ + "requestDate = %tF %Jens Pelzetter
+ */
+@Entity
+@Table(name = "queue_items")
+public class QueueItem implements Serializable {
+
+ private static final long serialVersionUID = 396330385592074013L;
+
+ @Id
+ @Column(name = "queue_item_id")
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long queueItemId;
+
+ @OneToOne
+ @JoinColumn(name = "receiver_id")
+ private Party receiver;
+
+ @Column(name = "retry_count")
+ private long retryCount;
+
+ @Column(name = "successful;")
+ private boolean successful;
+
+ @Column(name = "receiver_address", length = 512)
+ private String receiverAddress;
+
+ @Column(name = "header", length = 4096)
+ private String header;
+
+ @Column(name = "signature", length = 4096)
+ private String signature;
+
+ @OneToOne
+ @JoinColumn(name = "message_id")
+ private Message message;
+
+ public long getQueueItemId() {
+ return queueItemId;
+ }
+
+ public void setQueueItemId(final long queueItemId) {
+ this.queueItemId = queueItemId;
+ }
+
+ public Party getReceiver() {
+ return receiver;
+ }
+
+ public void setReceiver(final Party receiver) {
+ this.receiver = receiver;
+ }
+
+ public long getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(final long retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public boolean isSuccessful() {
+ return successful;
+ }
+
+ public void setSuccessful(final boolean successful) {
+ this.successful = successful;
+ }
+
+ public String getReceiverAddress() {
+ return receiverAddress;
+ }
+
+ public void setReceiverAddress(final String receiverAddress) {
+ this.receiverAddress = receiverAddress;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void setHeader(final String header) {
+ this.header = header;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public void setSignature(final String signature) {
+ this.signature = signature;
+ }
+
+ public Message getMessage() {
+ return message;
+ }
+
+ public void setMessage(final Message message) {
+ this.message = message;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 59 * hash + (int) (this.queueItemId ^ (this.queueItemId >>> 32));
+ hash = 59 * hash + Objects.hashCode(this.receiver);
+ hash = 59 * hash + (int) (this.retryCount ^ (this.retryCount >>> 32));
+ hash = 59 * hash + (this.successful ? 1 : 0);
+ hash = 59 * hash + Objects.hashCode(this.receiverAddress);
+ hash = 59 * hash + Objects.hashCode(this.header);
+ hash = 59 * hash + Objects.hashCode(this.signature);
+ hash = 59 * hash + Objects.hashCode(this.message);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final QueueItem other = (QueueItem) obj;
+ if (this.queueItemId != other.getQueueItemId()) {
+ return false;
+ }
+ if (!Objects.equals(this.receiver, other.getReceiver())) {
+ return false;
+ }
+ if (this.retryCount != other.getRetryCount()) {
+ return false;
+ }
+ if (this.successful != other.isSuccessful()) {
+ return false;
+ }
+ if (!Objects.equals(this.receiverAddress, other.getReceiverAddress())) {
+ return false;
+ }
+ if (!Objects.equals(this.header, other.getHeader())) {
+ return false;
+ }
+ if (!Objects.equals(this.signature, other.getSignature())) {
+ return false;
+ }
+ return Objects.equals(this.message, other.getMessage());
+ }
+
+ public boolean canEqual(final Object obj) {
+ return obj instanceof QueueItem;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s{ "
+ + "queueItemId = %d, "
+ + "receiver = %s, "
+ + "retryCount = %d, "
+ + "successful = %b, "
+ + "receiverAddress = \"%s\", "
+ + "message = %s"
+ + " }",
+ super.toString(),
+ queueItemId,
+ Objects.toString(receiver),
+ retryCount,
+ successful,
+ receiverAddress,
+ Objects.toString(message));
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/portal/Portal.java b/ccm-core/src/main/java/org/libreccm/portal/Portal.java
new file mode 100644
index 000000000..310ee12f1
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/portal/Portal.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.portal;
+
+import org.libreccm.core.Resource;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "portals")
+public class Portal extends Resource implements Serializable {
+
+ private static final long serialVersionUID = -5492307663469206053L;
+
+ @Column(name = "template")
+ private boolean template;
+
+ @OneToMany(mappedBy = "portal")
+ private List portlets;
+
+ public Portal() {
+ super();
+
+ portlets = new ArrayList<>();
+ }
+
+ public boolean isTemplate() {
+ return template;
+ }
+
+ public void setTemplate(final boolean template) {
+ this.template = template;
+ }
+
+ public List getPortlets() {
+ return Collections.unmodifiableList(portlets);
+ }
+
+ protected void setPortlets(final List portlets) {
+ this.portlets = portlets;
+ }
+
+ protected void addPortlet(final Portlet portlet) {
+ portlets.add(portlet);
+ }
+
+ protected void removePortlet(final Portlet portlet) {
+ portlets.remove(portlet);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ hash = 79 * hash + (template ? 1 : 0);
+ hash = 79 * hash + Objects.hashCode(portlets);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ if (!super.equals(obj)) {
+ return false;
+ }
+
+ final Portal other = (Portal) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+
+ if (template != other.isTemplate()) {
+ return false;
+ }
+ return Objects.equals(portlets, other.getPortlets());
+ }
+
+ @Override
+ public boolean canEqual(final Object obj) {
+ return obj instanceof Portal;
+ }
+
+ @Override
+ public String toString(final String data) {
+ return super.toString(String.format(", template = %b%s",
+ template,
+ data));
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/portal/Portlet.java b/ccm-core/src/main/java/org/libreccm/portal/Portlet.java
new file mode 100644
index 000000000..d12935852
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/portal/Portlet.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.portal;
+
+import org.libreccm.core.Resource;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ *
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "portlets")
+public class Portlet extends Resource implements Serializable {
+
+ private static final long serialVersionUID = -5718126018588744104L;
+
+ @ManyToOne
+ @JoinColumn(name = "portal_id")
+ private Portal portal;
+
+ @Column(name = "cell_number")
+ private long cellNumber;
+
+ @Column(name = "sort_key")
+ private long sortKey;
+
+ public Portal getPortal() {
+ return portal;
+ }
+
+ protected void setPortal(final Portal portal) {
+ this.portal = portal;
+ }
+
+ public long getCellNumber() {
+ return cellNumber;
+ }
+
+ public void setCellNumber(final long cellNumber) {
+ this.cellNumber = cellNumber;
+ }
+
+ public long getSortKey() {
+ return sortKey;
+ }
+
+ public void setSortKey(final long sortKey) {
+ this.sortKey = sortKey;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ hash = 97 * hash + Objects.hashCode(portal);
+ hash = 97 * hash + (int) (cellNumber ^ (cellNumber >>> 32));
+ hash = 97 * hash + (int) (sortKey ^ (sortKey >>> 32));
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ if (!super.equals(obj)) {
+ return false;
+ }
+
+ final Portlet other = (Portlet) obj;
+ if (!other.canEqual(obj)) {
+ return false;
+ }
+
+ if (!Objects.equals(portal, other.getPortal())) {
+ return false;
+ }
+ if (cellNumber != other.getCellNumber()) {
+ return false;
+ }
+ return sortKey == other.getSortKey();
+ }
+
+ @Override
+ public boolean canEqual(final Object obj) {
+ return obj instanceof Portlet;
+ }
+
+ @Override
+ public String toString(final String data) {
+ return super.toString(String.format(", portal = %s, "
+ + "cellNumber = %d, "
+ + "sortKey = %d%s",
+ Objects.toString(portal),
+ cellNumber,
+ sortKey,
+ data));
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/search/lucene/Document.java b/ccm-core/src/main/java/org/libreccm/search/lucene/Document.java
new file mode 100644
index 000000000..adc3f6877
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/search/lucene/Document.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.search.lucene;
+
+import org.libreccm.core.Party;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "lucene_documents")
+public class Document implements Serializable {
+
+ private static final long serialVersionUID = 3363154040440909619L;
+
+ @Id
+ @Column(name = "document_id")
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long documentId;
+
+ @Column(name = "type")
+ private String type;
+
+ @Column(name = "type_specific_info", length = 512)
+ private String typeSpecificInfo;
+
+ @Column(name = "document_timestamp")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date documentTimeStamp;
+
+ @Column(name = "dirty")
+ private long dirty;
+
+ @Column(name = "document_language", length = 8)
+ private String documentLanguage;
+
+ @Column(name = "country", length = 8)
+ private String country;
+
+ @Column(name = "title", length = 4096)
+ private String title;
+
+ @Column(name = "summary", length = 4096)
+ private String summary;
+
+ @Column(name = "content")
+ @Lob
+ private String content;
+
+ @Column(name = "created")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date created;
+
+ @OneToOne
+ @JoinColumn(name = "created_by_party_id")
+ private Party createdBy;
+
+ @Column(name = "last_modified")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date lastModified;
+
+ @OneToOne
+ @JoinColumn(name = "last_modified_by")
+ private Party lastModifiedBy;
+
+ @Column(name = "content_section", length = 512)
+ private String contentSection;
+
+ public Document() {
+ super();
+ }
+
+ public long getDocumentId() {
+ return documentId;
+ }
+
+ public void setDocumentId(final long documentId) {
+ this.documentId = documentId;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(final String type) {
+ this.type = type;
+ }
+
+ public String getTypeSpecificInfo() {
+ return typeSpecificInfo;
+ }
+
+ public void setTypeSpecificInfo(final String typeSpecificInfo) {
+ this.typeSpecificInfo = typeSpecificInfo;
+ }
+
+ public Date getDocumentTimeStamp() {
+ return new Date(documentTimeStamp.getTime());
+ }
+
+ public void setDocumentTimeStamp(final Date documentTimeStamp) {
+ this.documentTimeStamp = new Date(documentTimeStamp.getTime());
+ }
+
+ public long getDirty() {
+ return dirty;
+ }
+
+ public void setDirty(final long dirty) {
+ this.dirty = dirty;
+ }
+
+ public String getDocumentLanguage() {
+ return documentLanguage;
+ }
+
+ public void setDocumentLanguage(final String documentLanguage) {
+ this.documentLanguage = documentLanguage;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(final String country) {
+ this.country = country;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ public String getSummary() {
+ return summary;
+ }
+
+ public void setSummary(final String summary) {
+ this.summary = summary;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(final String content) {
+ this.content = content;
+ }
+
+ public Date getCreated() {
+ return new Date(created.getTime());
+ }
+
+ public void setCreated(final Date created) {
+ this.created = new Date(created.getTime());
+ }
+
+ public Party getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(final Party createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public Date getLastModified() {
+ return new Date(lastModified.getTime());
+ }
+
+ public void setLastModified(final Date lastModified) {
+ this.lastModified = new Date(lastModified.getTime());
+ }
+
+ public Party getLastModifiedBy() {
+ return lastModifiedBy;
+ }
+
+ public void setLastModifiedBy(final Party lastModifiedBy) {
+ this.lastModifiedBy = lastModifiedBy;
+ }
+
+ public String getContentSection() {
+ return contentSection;
+ }
+
+ public void setContentSection(final String contentSection) {
+ this.contentSection = contentSection;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 53 * hash + (int) (documentId ^ (documentId >>> 32));
+ hash = 53 * hash + Objects.hashCode(type);
+ hash = 53 * hash + Objects.hashCode(typeSpecificInfo);
+ hash = 53 * hash + Objects.hashCode(documentTimeStamp);
+ hash = 53 * hash + (int) (dirty ^ (dirty >>> 32));
+ hash = 53 * hash + Objects.hashCode(documentLanguage);
+ hash = 53 * hash + Objects.hashCode(country);
+ hash = 53 * hash + Objects.hashCode(title);
+ hash = 53 * hash + Objects.hashCode(summary);
+ hash = 53 * hash + Objects.hashCode(content);
+ hash = 53 * hash + Objects.hashCode(created);
+ hash = 53 * hash + Objects.hashCode(createdBy);
+ hash = 53 * hash + Objects.hashCode(lastModified);
+ hash = 53 * hash + Objects.hashCode(lastModifiedBy);
+ hash = 53 * hash + Objects.hashCode(contentSection);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Document other = (Document) obj;
+ if (documentId != other.getDocumentId()) {
+ return false;
+ }
+ if (!Objects.equals(type, other.getType())) {
+ return false;
+ }
+ if (!Objects.equals(typeSpecificInfo, other.getTypeSpecificInfo())) {
+ return false;
+ }
+ if (!Objects.equals(documentTimeStamp, other.getDocumentTimeStamp())) {
+ return false;
+ }
+ if (dirty != other.getDirty()) {
+ return false;
+ }
+ if (!Objects.equals(documentLanguage, other.getDocumentLanguage())) {
+ return false;
+ }
+ if (!Objects.equals(country, other.getCountry())) {
+ return false;
+ }
+ if (!Objects.equals(title, other.getTitle())) {
+ return false;
+ }
+ if (!Objects.equals(summary, other.getSummary())) {
+ return false;
+ }
+ if (!Objects.equals(content, other.getContent())) {
+ return false;
+ }
+ if (!Objects.equals(created, other.getCreated())) {
+ return false;
+ }
+ if (!Objects.equals(createdBy, other.getCreatedBy())) {
+ return false;
+ }
+ if (!Objects.equals(lastModified, other.getLastModified())) {
+ return false;
+ }
+ if (!Objects.equals(lastModifiedBy, other.getLastModifiedBy())) {
+ return false;
+ }
+ return Objects.equals(contentSection, other.getContentSection());
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s{ "
+ + "documentId = %d, "
+ + "type = \"%s\", "
+ + "documentTimeStamp = %tF %Jens Pelzetter
+ */
+@Entity
+@Table(name = "lucene_indexes")
+public class Index implements Serializable {
+
+ private static final long serialVersionUID = 3197625173477366719L;
+
+ @Id
+ @Column(name = "index_id")
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long indexId;
+
+ @OneToOne
+ @JoinColumn(name = "host_id")
+ private Host host;
+
+ @Column(name = "lucene_index_id")
+ private long luceneIndexId;
+
+ public Index() {
+ super();
+ }
+
+ public long getIndexId() {
+ return indexId;
+ }
+
+ public void setIndexId(final long indexId) {
+ this.indexId = indexId;
+ }
+
+ public Host getHost() {
+ return host;
+ }
+
+ public void setHost(final Host host) {
+ this.host = host;
+ }
+
+ public long getLuceneIndexId() {
+ return luceneIndexId;
+ }
+
+ public void setLuceneIndexId(final long luceneIndexId) {
+ this.luceneIndexId = luceneIndexId;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 89 * hash + (int) (indexId ^ (indexId >>> 32));
+ hash = 89 * hash + Objects.hashCode(host);
+ hash
+ = 89 * hash + (int) (luceneIndexId ^ (luceneIndexId >>> 32));
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Index other = (Index) obj;
+ if (indexId != other.getIndexId()) {
+ return false;
+ }
+ if (!Objects.equals(host, other.getHost())) {
+ return false;
+ }
+ return luceneIndexId == other.getLuceneIndexId();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s{ "
+ + "indexId = %d, "
+ + "host = %s, "
+ + "luceneIndexId = %d"
+ + " }",
+ super.toString(),
+ indexId,
+ Objects.toString(host),
+ luceneIndexId);
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/web/Application.java b/ccm-core/src/main/java/org/libreccm/web/Application.java
new file mode 100644
index 000000000..0b32f2f0b
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/web/Application.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.web;
+
+import org.libreccm.core.Resource;
+import org.libreccm.core.UserGroup;
+import org.libreccm.jpautils.UriConverter;
+
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "applications")
+public class Application extends Resource implements Serializable {
+
+ private static final long serialVersionUID = 9205226362368890784L;
+
+ @Column(name = "primary_url", length = 1024, nullable = false)
+ @Convert(converter = UriConverter.class)
+ private URI primaryUrl;
+
+ @OneToOne
+ @JoinColumn(name = "container_group_id")
+ private UserGroup containerGroup;
+
+ public URI getPrimaryUrl() {
+ return primaryUrl;
+ }
+
+ public void setPrimaryUrl(final URI primaryUrl) {
+ this.primaryUrl = primaryUrl;
+ }
+
+ public UserGroup getContainerGroup() {
+ return containerGroup;
+ }
+
+ public void setContainerGroup(final UserGroup containerGroup) {
+ this.containerGroup = containerGroup;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = super.hashCode();
+ hash = 97 * hash + Objects.hashCode(primaryUrl);
+ hash = 97 * hash + Objects.hashCode(containerGroup);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ if (!super.equals(obj)) {
+ return false;
+ }
+
+ final Application other = (Application) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+
+ if (!Objects.equals(primaryUrl, other.getPrimaryUrl())) {
+ return false;
+ }
+ return Objects.equals(containerGroup, other.getContainerGroup());
+ }
+
+ @Override
+ public String toString(final String data) {
+ return super.toString(String.format(", primaryUrl = \"%s\", "
+ + "containerGroup = %s%s",
+ primaryUrl,
+ Objects.toString(containerGroup),
+ data));
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/web/Host.java b/ccm-core/src/main/java/org/libreccm/web/Host.java
new file mode 100644
index 000000000..dfe9d8c80
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/web/Host.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package org.libreccm.web;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@Entity
+@Table(name = "hosts",
+ uniqueConstraints = {
+ @UniqueConstraint(columnNames = {"server_name", "server_port"})})
+public class Host implements Serializable {
+
+ private static final long serialVersionUID = 8727376444061847375L;
+
+ @Id
+ @Column(name = "host_id")
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long hostId;
+
+ @Column(name = "server_name", length = 512)
+ private String serverName;
+
+ @Column(name = "server_port")
+ private long serverPort;
+
+ public long getHostId() {
+ return hostId;
+ }
+
+ public void setHostId(final long hostId) {
+ this.hostId = hostId;
+ }
+
+ public String getServerName() {
+ return serverName;
+ }
+
+ public void setServerName(final String serverName) {
+ this.serverName = serverName;
+ }
+
+ public long getServerPort() {
+ return serverPort;
+ }
+
+ public void setServerPort(final long serverPort) {
+ this.serverPort = serverPort;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 79 * hash + (int) (this.hostId ^ (this.hostId >>> 32));
+ hash = 79 * hash + Objects.hashCode(this.serverName);
+ hash = 79 * hash + (int) (this.serverPort ^ (this.serverPort >>> 32));
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Host other = (Host) obj;
+ if (this.hostId != other.getHostId()) {
+ return false;
+ }
+ if (!Objects.equals(this.serverName, other.getServerName())) {
+ return false;
+ }
+ return this.serverPort == other.getServerPort();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s{ "
+ + "hostId = %d, "
+ + "serverName = \"%s\", "
+ + "serverPort =\"%s\""
+ + " }",
+ hostId,
+ serverName,
+ serverPort);
+ }
+
+}