View Javadoc

1   package net.sf.josceleton.connection.impl.service.motion;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   
6   import net.sf.josceleton.connection.api.Connection;
7   import net.sf.josceleton.connection.api.service.motion.MotionListener;
8   import net.sf.josceleton.core.api.entity.Coordinate;
9   import net.sf.josceleton.core.api.entity.User;
10  import net.sf.josceleton.core.api.entity.joint.Joint;
11  import net.sf.josceleton.core.api.entity.message.JointMessage;
12  import net.sf.josceleton.core.api.entity.message.UserMessage;
13  import net.sf.josceleton.core.impl.async.DefaultAsyncFor;
14  import net.sf.josceleton.core.impl.entity.joint.SkeletonFactory;
15  import net.sf.josceleton.core.impl.entity.joint.SkeletonInternal;
16  
17  import com.google.inject.Inject;
18  import com.google.inject.assistedinject.Assisted;
19  
20  /**
21   * @since 0.4
22   */
23  class MotionSeparatorImpl
24  	extends DefaultAsyncFor<User, MotionListener>
25  	implements MotionSeparatorInternal {
26  	
27  	private final Connection connection;
28  	
29  	private final SkeletonFactory skeletonFactory;
30  	
31  	private final Map<User, SkeletonInternal> skeletonByUser = new HashMap<User, SkeletonInternal>();
32  	
33  	private int countAddedListeners = 0;
34  	
35  	
36  	@Inject MotionSeparatorImpl(@Assisted final Connection connection, final SkeletonFactory skeletonFactory) {
37  		this.connection = connection;
38  		this.skeletonFactory = skeletonFactory;
39  	}
40  
41  	/** {@inheritDoc} from {@link ConnectionListener} */
42  	@Override public final void onJointMessage(final JointMessage message) {
43  		final User msgUser = message.getUser();
44  		if(this.skeletonByUser.containsKey(msgUser) == false) {
45  			// no one is interested in joint messages for this user; see #beforeAddListener(User, MotionListener)
46  			return;
47  		}
48  		
49  		final Joint msgJoint = message.getJoint();
50  		final Coordinate msgCoordinate = message.getCoordinate();
51  		
52  		final SkeletonInternal skeleton = this.skeletonByUser.get(msgUser);
53  		skeleton.update(msgJoint, msgCoordinate);
54  		
55  		for (MotionListener currentListener : this.getListenersFor(msgUser)) {
56  			currentListener.onMoved(msgJoint, msgCoordinate, skeleton);
57  		}
58  	}
59  	
60  	/** {@inheritDoc} from {@link ConnectionListener} */
61  	@Override public final void onUserMessage(final UserMessage message) {
62  		// ignored as we are only interested in motions (joint messages) and select user by our own
63  	}
64  
65  	/** {@inheritDoc} from {@link DefaultAsyncFor} */
66  	@Override protected final void beforeAddListener(final User user, final MotionListener listener) {
67  		if(this.getListenersFor(user).contains(listener) == false) {
68  			this.countAddedListeners++;
69  			
70  			if(this.countAddedListeners == 1) {
71  				this.connection.addListener(this);
72  			}
73  		}
74  
75  		if(this.skeletonByUser.containsKey(user) == false) {
76  			// the very first one
77  			final SkeletonInternal newSkeleton = this.skeletonFactory.create();
78  			this.skeletonByUser.put(user, newSkeleton);
79  		} 
80  	}
81  
82  	/** {@inheritDoc} from {@link DefaultAsyncFor} */
83  	@Override protected final void beforeRemoveListener(final User user, final MotionListener listener) {
84  		if(this.getListenersFor(user).contains(listener) == true) {
85  			this.countAddedListeners--;
86  			
87  			if(this.countAddedListeners == 0) {
88  				this.connection.removeListener(this);
89  				this.skeletonByUser.clear(); // wipe out all skeletons! muhahahahaha!!!!!!!!!
90  			}
91  		}
92  		
93  		
94  		// NO check if delete specific skeleton instance; keep it for future use (takes not that much memory)
95  		// also would need an afterRemoveListener() to remove Skeleton if no one is registered for this user anymore
96  	}
97  	
98  	
99  }