/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning 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 com.ning.billing.entitlement.events;
import com.ning.billing.entitlement.events.user.ApiEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
import org.joda.time.DateTime;
import java.util.UUID;
public abstract class EventBase implements EntitlementEvent {
private final UUID uuid;
private final UUID subscriptionId;
private final DateTime requestedDate;
private final DateTime effectiveDate;
private final DateTime processedDate;
// Lifecyle of the event
private long activeVersion;
private boolean isActive;
private UUID processingOwner;
private DateTime nextAvailableProcessingTime;
private EventLifecycleState processingState;
public EventBase(EventBaseBuilder builder) {
this.uuid = builder.getUuid();
this.subscriptionId = builder.getSubscriptionId();
this.requestedDate = builder.getRequestedDate();
this.effectiveDate = builder.getEffectiveDate();
this.processedDate = builder.getProcessedDate();
this.activeVersion = builder.getActiveVersion();
this.isActive = builder.isActive();
this.processingOwner = builder.getProcessingOwner();
this.nextAvailableProcessingTime = builder.getNextAvailableProcessingTime();
this.processingState = builder.getProcessingState();
}
public EventBase(UUID subscriptionId, DateTime requestedDate,
DateTime effectiveDate, DateTime processedDate,
long activeVersion, boolean isActive) {
this(subscriptionId, requestedDate, effectiveDate, processedDate, activeVersion, isActive, null, null, EventLifecycleState.AVAILABLE);
}
private EventBase(UUID subscriptionId, DateTime requestedDate,
DateTime effectiveDate, DateTime processedDate,
long activeVersion, boolean isActive,
UUID processingOwner, DateTime nextAvailableProcessingTime,
EventLifecycleState processingState) {
this(UUID.randomUUID(), subscriptionId, requestedDate, effectiveDate, processedDate, activeVersion, isActive,
processingOwner, nextAvailableProcessingTime, processingState);
}
public EventBase(UUID id, UUID subscriptionId, DateTime requestedDate,
DateTime effectiveDate, DateTime processedDate,
long activeVersion, boolean isActive,
UUID processingOwner, DateTime nextAvailableProcessingTime,
EventLifecycleState processingState) {
this.uuid = id;
this.subscriptionId = subscriptionId;
this.requestedDate = requestedDate;
this.effectiveDate = effectiveDate;
this.processedDate = processedDate;
this.activeVersion = activeVersion;
this.isActive = isActive;
this.processingOwner = processingOwner;
this.nextAvailableProcessingTime = nextAvailableProcessingTime;
this.processingState = processingState;
}
@Override
public DateTime getRequestedDate() {
return requestedDate;
}
@Override
public DateTime getEffectiveDate() {
return effectiveDate;
}
@Override
public DateTime getProcessedDate() {
return processedDate;
}
@Override
public UUID getSubscriptionId() {
return subscriptionId;
}
@Override
public UUID getId() {
return uuid;
}
@Override
public long getActiveVersion() {
return activeVersion;
}
@Override
public void setActiveVersion(long activeVersion) {
this.activeVersion = activeVersion;
}
@Override
public boolean isActive() {
return isActive;
}
@Override
public void deactivate() {
this.isActive = false;
}
@Override
public void reactivate() {
this.isActive = true;
}
@Override
public UUID getOwner() {
return processingOwner;
}
@Override
public void setOwner(UUID owner) {
this.processingOwner = owner;
}
@Override
public DateTime getNextAvailableDate() {
return nextAvailableProcessingTime;
}
@Override
public void setNextAvailableDate(DateTime dateTime) {
this.nextAvailableProcessingTime = dateTime;
}
@Override
public EventLifecycleState getProcessingState() {
return processingState;
}
@Override
public void setProcessingState(EventLifecycleState processingState) {
this.processingState = processingState;
}
@Override
public boolean isAvailableForProcessing(DateTime now) {
// Event got deactivated, will never be processed
if (!isActive) {
return false;
}
switch(processingState) {
case AVAILABLE:
break;
case IN_PROCESSING:
// Somebody already got the event, not available yet
if (nextAvailableProcessingTime.isAfter(now)) {
return false;
}
break;
case PROCESSED:
return false;
default:
throw new EntitlementError(String.format("Unkwnon IEvent processing state %s", processingState));
}
return effectiveDate.isBefore(now);
}
//
// Really used for unit tesrs only as the sql implementation relies on date first and then event insertion
//
// Order first by:
// - effectiveDate, followed by processedDate, requestedDate
// - if all dates are equal-- unlikely, we first return PHASE EVENTS
// - If both events are User events, return the first CREATE, CHANGE,... as specified by ApiEventType
// - If all that is not enough return consistent by random ordering based on UUID
//
@Override
public int compareTo(EntitlementEvent other) {
if (other == null) {
throw new NullPointerException("IEvent is compared to a null instance");
}
if (effectiveDate.isBefore(other.getEffectiveDate())) {
return -1;
} else if (effectiveDate.isAfter(other.getEffectiveDate())) {
return 1;
} else if (processedDate.isBefore(other.getProcessedDate())) {
return -1;
} else if (processedDate.isAfter(other.getProcessedDate())) {
return 1;
} else if (requestedDate.isBefore(other.getRequestedDate())) {
return -1;
} else if (requestedDate.isAfter(other.getRequestedDate())) {
return 1;
} else if (getType() != other.getType()) {
return (getType() == EventType.PHASE) ? -1 : 1;
} else if (getType() == EventType.API_USER) {
return ((ApiEvent) this).getEventType().compareTo(((ApiEvent) other).getEventType());
} else {
return uuid.compareTo(other.getId());
}
}
@Override
public boolean equals(Object other) {
if (! (other instanceof EntitlementEvent)) {
return false;
}
return (this.compareTo((EntitlementEvent) other) == 0);
}
@Override
public abstract EventType getType();
}