View Javadoc

1   /**
2    * 
3    */
4   package org.ximtec.igesture.core.composite;
5   
6   import java.text.ParseException;
7   import java.util.Calendar;
8   import java.util.Date;
9   import java.util.HashMap;
10  import java.util.HashSet;
11  import java.util.Iterator;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Set;
15  
16  import org.ximtec.igesture.core.Gesture;
17  import org.ximtec.igesture.io.IDeviceManager;
18  
19  /**
20   * This class represents a sequence constraint. All gestures have to be performed in the order they were defined. A minimum 
21   * and a maximum time interval between two consecutive gestures has to be defined.
22   * 
23   * @author Bjorn Puype, bpuype@gmail.com
24   *
25   */
26  public class SequenceConstraint extends DefaultConstraint {
27  
28  	public enum Config{
29  		MIN_TIME, MAX_TIME
30  	}
31  	
32  	private static final String MIN_TIME = "00:00:01.000";
33  	private static final String MAX_TIME = "00:00:10.000";
34  	
35  	private Calendar minTime;
36  	private Calendar maxTime;
37  	
38  	public SequenceConstraint() {
39  		super();
40  		DEFAULT_CONFIGURATION.put(Config.MIN_TIME.name(), MIN_TIME);
41  		DEFAULT_CONFIGURATION.put(Config.MAX_TIME.name(), MAX_TIME);
42  		setterMapping.put(Config.MIN_TIME.name(), "setMinTime");
43  		setterMapping.put(Config.MAX_TIME.name(), "setMaxTime");
44  		try {
45  			setMinTime(MIN_TIME);
46  			setMaxTime(MAX_TIME);
47  		} catch (ParseException e) {
48  			e.printStackTrace();
49  		}
50  		
51  	}
52  	
53  	/**
54  	 * Set the minimum time between two gestures
55  	 * @param time	minimum time in format "hh:mm:ss.SSS"
56  	 * @throws ParseException thrown if the minimum time could not be parsed
57  	 */
58  	public void setMinTime(String time) throws ParseException//int hours, int min, int seconds, int milliseconds
59  	{
60  		Date d = df.parse(time);
61  		minTime = Calendar.getInstance();
62  		minTime.setTime(d);	
63  	}
64  	
65  	/**
66  	 * Set the maximum time between two gestures
67  	 * @param time	maximum time in format "hh:mm:ss.SSS"
68  	 * @throws ParseException thrown if the maximum time could not be parsed
69  	 */
70  	public void setMaxTime(String time) throws ParseException
71  	{
72  		Date d = df.parse(time);
73  		maxTime = Calendar.getInstance();
74  		maxTime.setTime(d);
75  	}
76  	
77  	/**
78  	 * Get the minimum time between two gestures
79  	 */
80  	public Calendar getMinTime()
81  	{
82  		return minTime;
83  	}
84  	
85  	/**
86  	 * Get the maximum time between two gestures
87  	 */
88  	public Calendar getMaxTime()
89  	{
90  		return maxTime;
91  	}
92  	
93  	/* (non-Javadoc)
94  	 * @see org.ximtec.igesture.core.composite.DefaultConstraint#determineTimeWindows()
95  	 */
96  	@Override
97  	public Map<String, Calendar> determineTimeWindows() {
98  		
99  		Map<String, Calendar> map = new HashMap<String, Calendar>();
100 		
101 		int i = 0;
102 		int size = gestures.size();
103 		for(Iterator<DefaultConstraintEntry> iterator = gestures.iterator(); iterator.hasNext();i++)
104 		{
105 			DefaultConstraintEntry entry = iterator.next();
106 			//processing time
107 			Calendar cal = (Calendar) processingTime.clone();
108 			//time to perform gestures
109 			cal.add(Calendar.SECOND, (size-i)*gestureTime.get(Calendar.SECOND));
110 			//intervals
111 			cal.add(Calendar.SECOND, (size-1-i)*maxTime.get(Calendar.SECOND));
112 			cal.add(Calendar.MINUTE, (size-1-i)*maxTime.get(Calendar.MINUTE));
113 			cal.add(Calendar.HOUR, (size-1-i)*maxTime.get(Calendar.HOUR));
114 			
115 			if(map.containsKey(entry.getGesture()))
116 			{
117 				Calendar cal2 = map.get(entry.getGesture());
118 				if(cal2.after(cal))
119 					map.put(entry.getGesture(), cal2);
120 			}
121 			else
122 				map.put(entry.getGesture(), cal);
123 		}
124 		
125 		return map;
126 	}
127 
128 	/* (non-Javadoc)
129 	 * @see org.ximtec.igesture.core.composite.DefaultConstraint#generatePatterns(java.util.Map)
130 	 */
131 	@Override
132 	public Set<String> generatePatterns(Map<String, String> charMapping) {
133 		
134 		Set<String> patterns = new HashSet<String>();
135 		
136 		StringBuilder builder = new StringBuilder();
137 		for (DefaultConstraintEntry entry : gestures) {
138 			builder.append(charMapping.get(entry.getGesture()));			
139 		}
140 		
141 		patterns.add(builder.toString());
142 		
143 		return patterns;
144 	}
145 
146 	/* (non-Javadoc)
147 	 * @see org.ximtec.igesture.core.composite.DefaultConstraint#validateConditions(java.util.List)
148 	 */
149 	@Override
150 	public boolean validateConditions(List<Gesture<?>> gestures, IDeviceManager manager) {
151 		boolean conditionsValid = super.validateConditions(gestures, manager);
152 			
153 		if(conditionsValid) // if previous conditions hold
154 		{
155 			/* time check */
156 			//get end time of first gesture
157 			Iterator<Gesture<?>> iterator = gestures.iterator();
158 			Gesture<?> previousGesture = iterator.next();
159 			long prevEndTimestamp = getTimeStamp(previousGesture, false);
160 
161 			//for all consecutive gestures, check if they start after the previous one has ended
162 			for (; iterator.hasNext();) {
163 				Gesture<?> gesture = iterator.next();
164 				long startTimestamp = getTimeStamp(gesture, true);
165 				long gap = startTimestamp - prevEndTimestamp;
166 				if(gap >= 0 && gap > ConstraintTool.calculateTimeInMillis(minTime) && gap < ConstraintTool.calculateTimeInMillis(maxTime))//startTimestamp > prevEndTimestamp
167 				{
168 					prevEndTimestamp = getTimeStamp(gesture, false);
169 				}
170 				else
171 				{
172 					conditionsValid = false;
173 					break;
174 				}
175 			}
176 		}
177 		
178 		return conditionsValid;
179 	}
180 	
181 	public String toString()
182 	{
183 		return SequenceConstraint.class.getSimpleName();
184 	}
185 
186 }