/**
* C-Nery - A home automation web application for C-Bus.
* Copyright (C) 2008,2009,2012 Dave Oxley <dave@daveoxley.co.uk>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.daveoxley.cnery.entities;
import com.daveoxley.cbus.CGateException;
import com.daveoxley.cbus.CGateSession;
import com.daveoxley.cbus.Group;
import com.daveoxley.cnery.util.Sun;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.jboss.seam.Component;
import org.jboss.seam.contexts.Contexts;
/**
*
* @author Dave Oxley <dave@daveoxley.co.uk>
*/
@MappedSuperclass
public abstract class AbstractCondition<T extends AbstractCondition<T>> extends BaseEntity implements Serializable {
public enum ActionType {
TIME("cn.enum.AbstractCondition.ActionType.Time"),
GROUP("cn.enum.AbstractCondition.ActionType.Group"),
SCENE("cn.enum.AbstractCondition.ActionType.Scene"),
LOGIC("cn.enum.AbstractCondition.ActionType.Logic");
private final String description;
ActionType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
};
public enum TimeAfterBefore {
BEFORE("cn.enum.AbstractCondition.TimeAfterBefore.Before"),
AFTER("cn.enum.AbstractCondition.TimeAfterBefore.After");
private final String description;
TimeAfterBefore(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
};
public enum TimeWhen {
SUNSET("cn.enum.AbstractCondition.TimeWhen.Sunset"),
SUNRISE("cn.enum.AbstractCondition.TimeWhen.Sunrise"),
MIDNIGHT("cn.enum.AbstractCondition.TimeWhen.Midnight");
private final String description;
TimeWhen(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
};
public enum TimePlusMinus {
PLUS("cn.enum.AbstractCondition.TimePlusMinus.Plus"),
MINUS("cn.enum.AbstractCondition.TimePlusMinus.Minus");
private final String description;
TimePlusMinus(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
};
public enum SceneGroupOnOff {
GROUP_ON("cn.enum.AbstractCondition.SceneGroupOnOff.GroupOn"),
GROUP_OFF("cn.enum.AbstractCondition.SceneGroupOnOff.GroupOff"),
SCENE_ACTIVE("cn.enum.AbstractCondition.SceneGroupOnOff.SceneActive"),
SCENE_INACTIVE("cn.enum.AbstractCondition.SceneGroupOnOff.SceneInactive");
private final String description;
SceneGroupOnOff(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
};
public enum Logic {
AND("cn.enum.AbstractCondition.Logic.And"),
OR("cn.enum.AbstractCondition.Logic.Or");
private final String description;
Logic(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
};
private T parent;
private ActionType actionType;
private TimeAfterBefore timeAfterBefore;
private TimeWhen timeWhen;
private TimePlusMinus timePlusMinus;
private int timeMinutes;
private String dependGroup;
private Scene dependScene;
private SceneGroupOnOff sceneGroupOnOff;
private Logic logic;
@ManyToOne
@JoinColumn(name="parent_id")
public T getParent() { return parent; }
public void setParent(T parent) { this.parent = parent; }
@Column(name="action_type")
@Enumerated(EnumType.STRING)
public ActionType getActionType() { return actionType; }
public void setActionType(ActionType actionType) { this.actionType = actionType; }
@Column(name="time_after_before")
@Enumerated(EnumType.STRING)
public TimeAfterBefore getTimeAfterBefore() { return timeAfterBefore; }
public void setTimeAfterBefore(TimeAfterBefore timeAfterBefore) { this.timeAfterBefore = timeAfterBefore; }
@Column(name="time_when")
@Enumerated(EnumType.STRING)
public TimeWhen getTimeWhen() { return timeWhen; }
public void setTimeWhen(TimeWhen timeWhen) { this.timeWhen = timeWhen; }
@Column(name="time_plus_minus")
@Enumerated(EnumType.STRING)
public TimePlusMinus getTimePlusMinus() { return timePlusMinus; }
public void setTimePlusMinus(TimePlusMinus timePlusMinus) { this.timePlusMinus = timePlusMinus; }
@Column(name="time_minutes")
public int getTimeMinutes() { return timeMinutes; }
public void setTimeMinutes(int timeMinutes) { this.timeMinutes = timeMinutes; }
@Column(name="depend_group")
public String getDependGroup() { return dependGroup; }
public void setDependGroup(String dependGroup) { this.dependGroup = dependGroup; }
@ManyToOne(targetEntity=Scene.class)
@JoinColumn(name="depend_scene_id")
public Scene getDependScene() { return dependScene; }
public void setDependScene(Scene dependScene) { this.dependScene = dependScene; }
@Column(name="scene_group_on_off")
public SceneGroupOnOff getSceneGroupOnOff() { return sceneGroupOnOff; }
public void setSceneGroupOnOff(SceneGroupOnOff sceneGroupOnOff) { this.sceneGroupOnOff = sceneGroupOnOff; }
@Column(name="logic")
public Logic getLogic() { return logic; }
public void setLogic(Logic logic) { this.logic = logic; }
@Transient
public String getDependGroupName() {
try {
Group group = getDependCBusGroup();
if (group != null)
return group.getName();
} catch(Exception e) {
new CGateException(e);
}
return "";
}
@Transient
public Group getDependCBusGroup() throws CGateException {
String address = getDependGroup();
if (address == null)
return null;
CGateSession cGateSession = (CGateSession)Contexts.getApplicationContext().get("cGateSession");
return (Group)cGateSession.getCGateObject(address);
}
@Transient
public String getDependSceneName() {
Scene scene = getDependScene();
if (scene != null)
return scene.getName();
return "";
}
@Transient
public SceneGroupOnOff getSceneOnOff() {
if (getActionType().equals(ActionType.SCENE))
return sceneGroupOnOff;
return SceneGroupOnOff.SCENE_ACTIVE;
}
public void setSceneOnOff(SceneGroupOnOff sceneGroupOnOff) {
if (getActionType().equals(ActionType.SCENE))
this.sceneGroupOnOff = sceneGroupOnOff;
}
@Transient
public SceneGroupOnOff getGroupOnOff() {
if (getActionType().equals(ActionType.GROUP))
return sceneGroupOnOff;
return SceneGroupOnOff.GROUP_ON;
}
public void setGroupOnOff(SceneGroupOnOff sceneGroupOnOff) {
if (getActionType().equals(ActionType.GROUP))
this.sceneGroupOnOff = sceneGroupOnOff;
}
public GregorianCalendar getActionGregorian(GregorianCalendar currentTime) {
if (getActionType() != ActionType.TIME)
throw new IllegalStateException();
int minutes = getTimeMinutes();
if (getTimePlusMinus() == TimePlusMinus.MINUS) {
minutes *= -1;
}
else if (getTimePlusMinus() != TimePlusMinus.PLUS)
throw new IllegalStateException();
Sun sun = (Sun)Component.getInstance("sun");
GregorianCalendar adjustedTime = (GregorianCalendar)currentTime.clone();
adjustedTime.add(Calendar.MINUTE, minutes * -1);
GregorianCalendar actionTime;
if (getTimeAfterBefore() == TimeAfterBefore.AFTER) {
if (getTimeWhen() == TimeWhen.SUNSET) {
actionTime = sun.previousSunset(adjustedTime);
}
else if (getTimeWhen() == TimeWhen.SUNRISE) {
actionTime = sun.previousSunrise(adjustedTime);
}
else if (getTimeWhen() == TimeWhen.MIDNIGHT) {
actionTime = (GregorianCalendar)adjustedTime.clone();
actionTime.set(Calendar.HOUR_OF_DAY, 0);
actionTime.set(Calendar.MINUTE, 0);
actionTime.set(Calendar.SECOND, 0);
actionTime.set(Calendar.MILLISECOND, 0);
}
else
throw new IllegalStateException();
}
else if (getTimeAfterBefore() == TimeAfterBefore.BEFORE) {
if (getTimeWhen() == TimeWhen.SUNSET) {
actionTime = sun.nextSunset(adjustedTime);
}
else if (getTimeWhen() == TimeWhen.SUNRISE) {
actionTime = sun.nextSunrise(adjustedTime);
}
else if (getTimeWhen() == TimeWhen.MIDNIGHT) {
actionTime = (GregorianCalendar)adjustedTime.clone();
actionTime.add(Calendar.DAY_OF_YEAR, 1);
actionTime.set(Calendar.HOUR_OF_DAY, 0);
actionTime.set(Calendar.MINUTE, 0);
actionTime.set(Calendar.SECOND, 0);
actionTime.set(Calendar.MILLISECOND, 0);
}
else
throw new IllegalStateException();
}
else
throw new IllegalStateException();
actionTime.add(Calendar.MINUTE, minutes);
return actionTime;
}
@Transient
public String getActiveActionTime() {
if (getActionType() != ActionType.TIME)
return "";
GregorianCalendar currentTime = new GregorianCalendar();
GregorianCalendar previousActionTime = getActionGregorian(currentTime);
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
String previousActionTimeString = "Today at ";
if (previousActionTime.get(Calendar.DAY_OF_YEAR) < currentTime.get(Calendar.DAY_OF_YEAR))
previousActionTimeString = "Yesterday at ";
else if (previousActionTime.get(Calendar.DAY_OF_YEAR) > currentTime.get(Calendar.DAY_OF_YEAR))
previousActionTimeString = "Tomorrow at ";
return previousActionTimeString + formatter.format(previousActionTime.getTime());
}
public GregorianCalendar getNextActionGregorian(GregorianCalendar currentTime) {
if (getActionType() != ActionType.TIME)
throw new IllegalStateException();
int minutes = getTimeMinutes();
if (getTimePlusMinus() == TimePlusMinus.MINUS) {
minutes *= -1;
}
else if (getTimePlusMinus() != TimePlusMinus.PLUS)
throw new IllegalStateException();
Sun sun = (Sun)Component.getInstance("sun");
GregorianCalendar adjustedTime = (GregorianCalendar)currentTime.clone();
adjustedTime.add(Calendar.MINUTE, minutes * -1);
GregorianCalendar actionTime;
if (getTimeWhen() == TimeWhen.SUNSET) {
actionTime = sun.nextSunset(adjustedTime);
}
else if (getTimeWhen() == TimeWhen.SUNRISE) {
actionTime = sun.nextSunrise(adjustedTime);
}
else if (getTimeWhen() == TimeWhen.MIDNIGHT) {
actionTime = (GregorianCalendar)adjustedTime.clone();
actionTime.add(Calendar.DAY_OF_YEAR, 1);
actionTime.set(Calendar.HOUR_OF_DAY, 0);
actionTime.set(Calendar.MINUTE, 0);
actionTime.set(Calendar.SECOND, 0);
actionTime.set(Calendar.MILLISECOND, 0);
}
else
throw new IllegalStateException();
actionTime.add(Calendar.MINUTE, minutes);
return actionTime;
}
@Transient
public String getNextActionTime() {
if (getActionType() != ActionType.TIME)
return "";
GregorianCalendar currentTime = new GregorianCalendar();
GregorianCalendar nextActionTime = getNextActionGregorian(currentTime);
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
String nextActionTimeString = "Today at ";
if (nextActionTime.get(Calendar.DAY_OF_YEAR) > currentTime.get(Calendar.DAY_OF_YEAR))
nextActionTimeString = "Tomorrow at ";
return nextActionTimeString + formatter.format(nextActionTime.getTime());
}
}