001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.client.tide.impl;
022    
023    import java.util.concurrent.ExecutionException;
024    
025    import org.granite.client.messaging.events.CancelledEvent;
026    import org.granite.client.messaging.events.FailureEvent;
027    import org.granite.client.messaging.events.FaultEvent;
028    import org.granite.client.messaging.events.ResultEvent;
029    import org.granite.client.messaging.events.TimeoutEvent;
030    import org.granite.client.tide.Context;
031    import org.granite.client.tide.server.Component;
032    import org.granite.client.tide.server.ComponentListener;
033    import org.granite.client.tide.server.FaultException;
034    import org.granite.client.tide.server.TideResponder;
035    
036    /**
037     * @author William DRAI
038     */
039    public class ComponentListenerImpl<T> implements ComponentListener<T> {
040        
041        private Context sourceContext;
042        private Component component;
043        private String componentName;
044        private String operation;
045        private Object[] args;
046        private Handler<T> handler;
047        private TideResponder<T> tideResponder;
048        private Object info;
049        private boolean waiting = false;
050        private Runnable responseHandler = null;
051        private T result = null;
052        private Exception exception = null;
053        
054        
055        public ComponentListenerImpl(Context sourceContext, Handler<T>handler, Component component, String operation, Object[] args, Object info, TideResponder<T> tideResponder) {        
056            this.sourceContext = sourceContext;
057            this.handler = handler;
058            this.component = component;
059            this.componentName = component != null ? component.getName() : null;
060            this.operation = operation;
061            this.args = args;
062            this.tideResponder = tideResponder;
063            this.info = info;
064        }
065        
066        public String getOperation() {
067            return operation;
068        }
069        
070        public Object[] getArgs() {
071            return args;
072        }
073        public void setArgs(Object[] args) {
074            this.args = args;
075        }
076        
077        public Context getSourceContext() {
078            return sourceContext;
079        }
080        
081        public Component getComponent() {
082            return component;
083        }
084        
085        public T getResult() throws InterruptedException, ExecutionException {
086            synchronized (this) {
087                    if (responseHandler == null && exception == null) {
088                            waiting = true;
089                            wait();
090                    }
091                    if (responseHandler != null)
092                            responseHandler.run();
093            }
094            if (exception instanceof ExecutionException)
095                    throw (ExecutionException)exception;
096            else if (exception instanceof InterruptedException)
097                    throw (InterruptedException)exception;
098            return result;
099        }
100        
101        public void setResult(T result) {
102            this.result = result;
103        }
104        
105            @Override
106        public void onResult(ResultEvent event) {
107                    Runnable h = handler.result(sourceContext, event, info, componentName, operation, tideResponder, this);
108            synchronized (this) {
109                    responseHandler = h;
110                    if (waiting)
111                            notifyAll();
112                    else
113                            sourceContext.callLater(h);
114            }
115        }
116        
117            @Override
118        public void onFault(FaultEvent event) {
119                    Runnable h = handler.fault(sourceContext, event, info, componentName, operation, tideResponder, this);
120                    synchronized (this) {
121                            responseHandler = h;
122                            exception = new FaultException(event);
123                            if (waiting)
124                                    notifyAll();
125                            else
126                            sourceContext.callLater(h);
127                    }
128        }
129    
130            @Override
131            public void onFailure(final FailureEvent event) {
132                    synchronized (this) {
133                            exception = new ExecutionException(event.getCause());
134                            if (waiting)
135                                    notifyAll();
136                    }
137            }
138    
139            @Override
140            public void onTimeout(TimeoutEvent event) {
141                    synchronized (this) {
142                            exception = new InterruptedException("timeout");
143                            if (waiting)
144                                    notifyAll();
145                    }
146            }
147    
148            @Override
149            public void onCancelled(CancelledEvent event) {
150                    synchronized (this) {
151                            exception = new InterruptedException("cancel");
152                            if (waiting)
153                                    notifyAll();
154                    }
155            }
156    }