package no.ntnu.fp.net.network.client; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InterruptedIOException; import java.io.ObjectOutputStream; import java.lang.reflect.Type; import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; import java.lang.reflect.ParameterizedType; import javax.net.ssl.HostnameVerifier; import org.jdom.adapters.XML4JDOMAdapter; import no.ntnu.fp.model.Appointment; import no.ntnu.fp.model.Authenticate; import no.ntnu.fp.model.Calendar; import no.ntnu.fp.model.CalendarEntry; import no.ntnu.fp.model.Location; import no.ntnu.fp.model.Meeting; import no.ntnu.fp.model.Meeting.State; import no.ntnu.fp.model.Place; import no.ntnu.fp.model.User; import no.ntnu.fp.model.XmlHandler; import no.ntnu.fp.net.network.Request; import no.ntnu.fp.net.network.Request.Method; import no.ntnu.fp.model.Room; //Static ? /** * @author bj0rn * This class provides the interface for the communication. * The methods can be used by the client to produce requests to the server * The methods are made to fake synchronization between the client and the server * * **/ //TODO: Find a way to notify the client model about notifications public class CommunicationController { public static String host = "78.91.22.12"; //"127.0.0.1"; // public final static int PORT = 1337; private static CommunicationController instance; //fields private BlockingQueue<Object> inQueue; private Socket mySocket; private UpdateHandler updateHandler; private LinkedBlockingDeque<Object> testQueue; // Models /** * The authentication used throughout the session. * Created by the {@code LoginFrame} */ private Authenticate auth; /** * The {@code User} for the client own {@code User} */ private User user; /** * A complete {@code List} of all {@code User}s */ private List<User> users; /** * A {@code List} of {@code User}s which the {@code user} shows. */ private List<User> shows; /** * The complete {@code List} of {@code Room}s. */ private List<Room> rooms; /** * A {@code List} of {@code Place}s. */ private List<Place> places; private DataOutputStream os; private ObjectOutputStream oos; final static String USER = "User"; public static void main(String[] args) { User u = new User("bjorn", "123"); List <User> users = new ArrayList<User>(); users.add(u); List test = (List) users; Object obj = test.get(0); System.out.println(obj.getClass().getSimpleName()); } //constructor private CommunicationController(){ LinkedBlockingDeque<Object> testQueue = new LinkedBlockingDeque<Object>(); //CommunicationController communicationController = new CommunicationController(mySocket, testQueue) Client c = new Client(host, PORT, testQueue, this); try { this.mySocket = c.getSocket(); os = new DataOutputStream(mySocket.getOutputStream()); updateHandler = new UpdateHandler(); this.testQueue = testQueue; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } new Thread(c).start(); } //TODO: Test if this approach works ? public static synchronized CommunicationController getInstance() { if (instance == null) { instance = new CommunicationController(); } return instance; } public static void setHost(String ip) { host = ip; } public void send(Socket socket, Object obj){ DataOutputStream os; try { os = new DataOutputStream(socket.getOutputStream()); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(obj); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void inspect(){ //When notifications arrive we need to be ready //How can we handle them ? } /** * This method will authenticate will login in the user to the server * **/ public boolean authenticate(Authenticate auth){ try { Request request = new Request(auth, null); request.setMethod(Request.Method.AUTHENTICATE); send(mySocket, request); setAuthunticate(auth); //Wait for response boolean good = false; int i = 0; while(!good){ Request response = (Request)testQueue.takeFirst(); System.out.println("Number of tries: "+i++); if(response.getMethod() == Request.Method.LOGIN_SUCCEDED){ return true; }else if(response.getMethod() == Request.Method.LOGIN_FAILED){ return false; } else { System.out.println("Put back"); testQueue.putLast((Object)response); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } private void setAuthunticate(Authenticate auth) { this.auth = auth; } public Authenticate getAuthenticate() { return auth; } public void addFullUser(User user) { int index = users.indexOf(user); users.remove(index); users.add(index, user); } /** * Retrieves the full {@code List} of {@code User}s once from the server. * Returns the {@code List}. * * @return */ public List<User> getListOfUsers() { if (users == null) { updateListOfUsers(); } return users; } /** * This method will get all the users from the server * **/ public void updateListOfUsers() { try { Request request = new Request(auth, null); request.setMethod(Request.Method.GET_USERS); send(mySocket, request); int i = 0; while(true){ System.out.println("Number of tries: "+i++); Request response = (Request) testQueue.takeFirst(); if(response.getMethod() == Request.Method.GET_USERS_RESPONSE){ users = (List<User>)response.getObject(); return; }else if (response.getMethod() == Request.Method.LOGIN_FAILED){ //return null; }else{ //Put it back and try again System.out.println("Put back"); testQueue.putLast((Object)response); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void addSelectedUser(User user) { System.out.println("add:" + user.getName()); if (!shows.contains(user)) shows.add(user); } public void removeSelectedUser(User user) { System.out.println("remove:" + user.getName()); int index = shows.indexOf(user); shows.remove(index); System.out.println(shows.size()); } public List<User> getSelectedUsers() { if (shows == null) { updateSelectedUsers(); } return shows; } public void updateSelectedUsers(){ try{ Request request = new Request(auth, null); request.setMethod(Method.GET_SUBSCRIBERS); send(mySocket, request); int i = 0; while(true){ System.out.println("Number of tries: "+i++); Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Method.GET_SUBSCRIBERS_RESPONSE){ System.out.println("Yey :) "); List<User> users = (List<User>)response.getObject(); shows = new ArrayList<User>(); for(User user : users) { shows.add(getFullUser(user.getUsername())); } return; }else if(response.getMethod() == Method.LOGIN_FAILED){ System.out.println("Not logged inn"); return; }else{ testQueue.putLast((Object)response); } } }catch(InterruptedException e){ e.printStackTrace(); } } /** * Retrieves the current connected {@code User} from the Server. * Stores the {@code User} and returns it to the caller * * @return the current connected {@code User} */ public User getClientFullUser() { return (user = getFullUser(auth.getUsername())); } /** * Retrieves the requested {@code User} from the Server. * Stores the {@code User} in {@code shows} and returns it to the caller. * @param username * @return */ public User getOtherFullUser(String username) { User user = getFullUser(username); //shows.put(user.getUsername(), user); return user; } public User getFullUser(String username){ getListOfUsers(); try { Request request = new Request(auth, username); request.setMethod(Request.Method.GET_FULL_USER); send(mySocket, request); int i = 0; while(true){ System.out.println("Number of tries: "+i++); Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Request.Method.GET_FULL_USER_RESPONSE){ User user = (User)response.getObject(); //cleanRefences(user); return user; } else if(response.getMethod() == Request.Method.LOGIN_FAILED){ return null; }else { System.out.println("Put back"); testQueue.putLast((Object)response); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private Map<String, User> mapOfUsers() { Map<String, User> mapOfUsers = new HashMap<String, User>(); for(User user : users) { mapOfUsers.put(user.getUsername(), user); } return mapOfUsers; } /* * */ private void cleanRefences(User fullUser) { Map<String, User> mapOfUsers = mapOfUsers(); Calendar calendar = fullUser.getCalendar(); for (CalendarEntry entry : calendar) { if (entry instanceof Meeting) { Meeting meeting = (Meeting)entry; cleanReferencesOnMeeting(meeting, mapOfUsers); } } } private void cleanReferencesOnMeeting(Meeting meeting, Map<String, User> mapOfUsers) { Set<Map.Entry<User, State>> participants = meeting.getParticipantsMap().entrySet(); /*Set<User> keySet = meeting.getParticipantsMap().keySet(); for (User user : keySet) { String username = user.getUsername(); User fullUser = mapOfUsers.get(username) }*/ meeting.removeAllParticipants(); for(Entry<User, State> entry : participants) { String username = entry.getKey().getUsername(); User user = mapOfUsers.get(username); State state = entry.getValue(); meeting.addParticipant(user, state); } } /** * Returns the current connected {@code User} * * @return */ public User getUser() { return user; } public int saveMeeting(Meeting meeting){ System.out.println(meeting.getID()); try{ Request request = new Request(auth, meeting); request.setMethod(Request.Method.SAVE_MEETING); send(mySocket, request); int i = 0; while(true){ System.out.println("Number of tries: "+i++); //This should be a response containing the key Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Request.Method.SAVE_MEETING_RESPONSE){ Integer key = (Integer)response.getObject(); System.out.println("Got key "+key); return key; }else if(response.getMethod() == Request.Method.LOGIN_FAILED){ return -1; } else { System.out.println("Put back"); testQueue.putLast((Object)response); } } }catch(InterruptedException e){ e.printStackTrace(); } return -1; } public int saveAppointment(Appointment appointment){ try{ Request request = new Request(auth, appointment); request.setMethod(Request.Method.SAVE_APPOINTMENT); //Does saveAppointment return a key send(mySocket, request); int i = 0; while(true){ System.out.println("Number of tries "); //This response should contain a key Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Request.Method.SAVE_APPOINTMENT_RESPONSE){ Integer id = (Integer)response.getObject(); return id; }else if(response.getMethod() == Request.Method.LOGIN_FAILED){ return -1; } else { System.out.println("Put back"); testQueue.putLast((Object)response); } } } catch(InterruptedException e) { e.printStackTrace(); } return -1; } public boolean dispatchMeetingReply(User user, Meeting meeting, State state) { try{ //Gather information String userInfo[] = { user.getUsername(), "", }; String dataValues[] = { user.getId(), String.valueOf(meeting.getID()), state.toString() }; //Pack and send String xml = XmlHandler.dispatchMeetingReplyToXml(userInfo, dataValues, "dispatchMeetingReply"); Request request = new Request(auth, xml); request.setMethod(Request.Method.DISPATCH_MEETING_REPLY); send(mySocket, request); int i = 0; //Wait for response while(true){ Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Method.SAVE_APPOINTMENT_RESPONSE){ return true; }else if(response.getMethod() == Method.LOGIN_FAILED){ return false; }else { System.out.println("Put back"); testQueue.putLast((Object)response); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } /** * Retrieves the full {@code List} of {@code Room}s once from the server. * Returns the {@code List}. * * @return */ public List<Room> getListOfRooms() { if (rooms == null) { updateListOfRooms(); } return rooms; } public void updateListOfRooms() { try{ Request request = new Request(auth, null); request.setMethod(Method.GET_LIST_OF_ROOMS); send(mySocket, request); int i = 0; while(true){ Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Method.GET_LIST_OF_ROOMS_RESPONSE){ rooms = (List <Room>)response.getObject(); return; }else if(response.getMethod() == Method.LOGIN_FAILED){ //return null; }else { System.out.println("Put back"); testQueue.putLast((Object)response); } } }catch(InterruptedException e){ e.printStackTrace(); } } /*public List <Room> getListOfRooms(){ try{ Request request = new Request(auth, null); request.setMethod(Method.GET_LIST_OF_ROOMS); send(mySocket, request); int i = 0; while(true){ Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Method.GET_LIST_OF_ROOMS_RESPONSE){ return (List <Room>)response.getObject(); }else if(response.getMethod() == Method.LOGIN_FAILED){ return null; }else { testQueue.putLast((Object)response); } } }catch(InterruptedException e){ e.printStackTrace(); } return null; }*/ public boolean cancelView(String username){ try { Request request = new Request(auth, username); request.setMethod(Method.CANCEL_VIEW); send(mySocket, request); int i = 0; while(true){ System.out.println("Number of tries: "+i++); Request response = (Request)testQueue.takeFirst(); if(response.getMethod() == Method.CANCEL_VIEW_SUCCEDED){ return true; }else if(response.getMethod() == Method.LOGIN_FAILED){ return false; }else { System.out.println("Put back"); testQueue.putLast((Object)response); } } }catch(InterruptedException e){ e.printStackTrace(); } return false; } public void deleteMeeting(Meeting meeting){ Integer id = meeting.getID(); Request request = new Request(auth, id); request.setMethod(Method.DELETE_MEETING); send(mySocket, request); } public void deleteAppointment(Appointment appointment){ Integer id = appointment.getID(); Request request = new Request(auth, id); request.setMethod(Method.DELETE_APPOINTMENT); send(mySocket, request); } public boolean deleteUser(){ return true; } /** * This method is called by the {@code ClientWorker} when a * {@code Meeting} update is received from the Server. * @param meeting */ public synchronized void updateMeeting(Meeting updatedMeeting) { User owner = updatedMeeting.getOwner(); Calendar calendar = user.getCalendar(); Meeting meeting = null; if (owner.equals(user)) { for (CalendarEntry entry : user.getCalendar()) { if (entry.getID() == updatedMeeting.getID()) { meeting = (Meeting)entry; continue; } } } else { for (User participant : updatedMeeting.getParticipants()) { if (participant.equals(user)) { for (CalendarEntry entry : participant.getCalendar()) { if (entry.getID() == updatedMeeting.getID()) { meeting = (Meeting) entry; continue; } } if (meeting == null ) { calendar.addMeeting(updatedMeeting); } } } } if (meeting != null) { calendar.addMeeting(updatedMeeting); } } public synchronized void updateMeetingState(Meeting updatedMeeting) { User owner = updatedMeeting.getOwner(); Calendar calendar = user.getCalendar(); Meeting meeting = null; if (owner.equals(user)) { System.out.println("my meeting"); for (CalendarEntry entry : user.getCalendar()) { System.out.println(entry.getID()); System.out.println(updatedMeeting.getID()); if (entry.getID() == updatedMeeting.getID()) { System.out.println("found meeting"); meeting = (Meeting)entry; continue; } } } else { for (User participant : updatedMeeting.getParticipants()) { if (participant.equals(user)) { for (CalendarEntry entry : participant.getCalendar()) { if (entry.getID() == updatedMeeting.getID()) { meeting = (Meeting) entry; continue; } } } } } if (meeting != null) { for (User user : meeting.getParticipants()) { System.out.println("changing: " + user.getUsername()); State state = meeting.getState(user); State updatedState = updatedMeeting.getState(user); if (state != updatedState) { meeting.setState(user, updatedState); } } System.out.println("state changed"); } } /** * * @param appointment */ public synchronized void updateAppointment(Appointment appointment) { User user = appointment.getOwner(); if(shows != null){ for(User u : shows){ if(u.equals(user)){ Calendar c = u.getCalendar(); c.removeAppointment(appointment); c.addAppointment(appointment); } } } } /** * Delete helper * * Iterates through all the entries and delete the entry * with the given id * * **/ private void deleteHelper(Calendar c, int id){ for(int i = 0; i < c.getNumEntries(); i++){ CalendarEntry e = c.get(i); if(e.getID() == id){ c.removeEntry(i); break; } } } /** * Called from clientWorker * **/ public synchronized void deleteEntry(int id){ Calendar c = user.getCalendar(); deleteHelper(c, id); if(shows != null){ for(User u: shows){ Calendar vc = u.getCalendar(); deleteHelper(vc, id); } } } /** * Called from clientWorker * * **/ public synchronized void deleteAppointment(int id){ } }