/** * 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()); } }