/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.axis.services;

import java.util.Date;
import java.util.List;

import org.apache.axis2.AxisFault;
import org.apache.openmeetings.db.dto.record.RecordingDTO;
import org.apache.openmeetings.db.dto.room.RoomDTO;
import org.apache.openmeetings.db.dto.room.RoomSearchResult;
import org.apache.openmeetings.db.entity.room.RoomType;

public class RoomWebServiceFacade extends BaseWebService {

	public List<RoomDTO> getRoomsPublic(String SID, Long roomtypes_id) throws AxisFault {
		return getBean(RoomWebService.class).getRoomsPublic(SID, roomtypes_id);
	}

	/**
	 * Deletes a flv recording
	 * 
	 * @param SID
	 *            The SID of the User. This SID must be marked as Loggedin
	 * @param flvRecordingId
	 *            the id of the recording
	 * @return
	 * @throws AxisFault
	 */
	public boolean deleteFlvRecording(String SID, Long flvRecordingId)
			throws AxisFault {
		return getBean(RoomWebService.class).deleteFlvRecording(SID,
				flvRecordingId);
	}

	public List<RecordingDTO> getFlvRecordingByExternalUserId(String SID,
			String externalUserId, String externalUserType) throws AxisFault {
		return getBean(RoomWebService.class).getFlvRecordingByExternalUserId(SID, externalUserId, externalUserType);
	}

	public List<RecordingDTO> getFlvRecordingByExternalRoomTypeAndCreator(
			String SID, String externalRoomType, Long insertedBy)
			throws AxisFault {
		return getBean(RoomWebService.class)
				.getFlvRecordingByExternalRoomTypeAndCreator(SID,
						externalRoomType, insertedBy);
	}

	public List<RecordingDTO> getFlvRecordingByExternalRoomTypeByList(String SID, String externalRoomType) throws AxisFault {
		return getBean(RoomWebService.class)
				.getFlvRecordingByExternalRoomTypeByList(SID, externalRoomType);
	}

	public List<RecordingDTO> getRecordingsByExternalType(String SID, String externalType) throws AxisFault {
		return getBean(RoomWebService.class).getRecordingsByExternalType(SID, externalType);
	}

	public List<RecordingDTO> getFlvRecordingByExternalRoomType(String SID, String externalRoomType) throws AxisFault {
		return getBean(RoomWebService.class).getFlvRecordingByExternalRoomType(SID, externalRoomType);
	}

	public List<RecordingDTO> getFlvRecordingByRoomId(String SID, Long roomId) throws AxisFault {
		return getBean(RoomWebService.class).getFlvRecordingByRoomId(SID, roomId);
	}

	public List<RoomType> getRoomTypes(String SID) throws AxisFault {
		return getBean(RoomWebService.class).getRoomTypes(SID);
	}

	public List<RoomCountBean> getRoomCounters(String SID, Integer[] roomId) throws AxisFault {
		return getBean(RoomWebService.class).getRoomCounters(SID, roomId);
	}

	public RoomDTO getRoomById(String SID, long rooms_id) throws AxisFault {
		return getBean(RoomWebService.class).getRoomById(SID, rooms_id);
	}

	public RoomReturn getRoomWithClientObjectsById(String SID, long rooms_id)
			throws AxisFault {
		return getBean(RoomWebService.class).getRoomWithClientObjectsById(SID,
				rooms_id);
	}

	public RoomSearchResult getRooms(String SID, int start, int max, String orderby, boolean asc) throws AxisFault {
		return getBean(RoomWebService.class).getRooms(SID, start, max, orderby, asc);
	}

	public RoomSearchResult getRoomsWithCurrentUsers(String SID, int start, int max, String orderby , boolean asc) throws AxisFault {
		return getBean(RoomWebService.class).getRoomsWithCurrentUsers(SID, start, max, orderby, asc);
	}

	public Long addRoomWithModeration(String SID, String name,
			Long roomtypes_id, String comment, Long numberOfPartizipants,
			Boolean ispublic, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom) throws AxisFault {
		return getBean(RoomWebService.class).addRoomWithModeration(SID, name,
				roomtypes_id, comment, numberOfPartizipants, ispublic,
				appointment, isDemoRoom, demoTime, isModeratedRoom);
	}

	/**
	 * this SOAP Method has an additional param to enable or disable the buttons
	 * to apply for moderation this does only work in combination with the
	 * room-type restricted
	 * 
	 * @param SID
	 * @param name
	 * @param roomtypes_id
	 * @param comment
	 * @param numberOfPartizipants
	 * @param ispublic
	 * @param appointment
	 * @param isDemoRoom
	 * @param demoTime
	 * @param isModeratedRoom
	 * @param allowUserQuestions
	 * @return
	 */
	public Long addRoomWithModerationAndQuestions(String SID, String name,
			Long roomtypes_id, String comment, Long numberOfPartizipants,
			Boolean ispublic, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom,
			Boolean allowUserQuestions) throws AxisFault {
		return getBean(RoomWebService.class).addRoomWithModerationAndQuestions(
				SID, name, roomtypes_id, comment, numberOfPartizipants,
				ispublic, appointment, isDemoRoom, demoTime, isModeratedRoom,
				allowUserQuestions);
	}

	public Long addRoomWithModerationQuestionsAndAudioType(String SID,
			String name, Long roomtypes_id, String comment,
			Long numberOfPartizipants, Boolean ispublic, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			Boolean allowUserQuestions, Boolean isAudioOnly) throws AxisFault {
		return getBean(RoomWebService.class)
				.addRoomWithModerationQuestionsAndAudioType(SID, name,
						roomtypes_id, comment, numberOfPartizipants, ispublic,
						appointment, isDemoRoom, demoTime, isModeratedRoom,
						allowUserQuestions, isAudioOnly);
	}

	/**
	 * 
	 * @param SID
	 * @param name
	 * @param roomtypes_id
	 * @param comment
	 * @param numberOfPartizipants
	 * @param ispublic
	 * @param appointment
	 * @param isDemoRoom
	 * @param demoTime
	 * @param isModeratedRoom
	 * @param externalRoomId
	 * @param externalUserType
	 * @return
	 */
	public Long getRoomIdByExternalId(String SID, String name,
			Long roomtypes_id, String comment, Long numberOfPartizipants,
			Boolean ispublic, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom, Long externalRoomId,
			String externalRoomType) throws AxisFault {
		return getBean(RoomWebService.class).getRoomIdByExternalId(SID, name,
				roomtypes_id, comment, numberOfPartizipants, ispublic,
				appointment, isDemoRoom, demoTime, isModeratedRoom,
				externalRoomId, externalRoomType);
	}

	public Long updateRoomWithModeration(String SID, Long room_id, String name,
			Long roomtypes_id, String comment, Long numberOfPartizipants,
			Boolean ispublic, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom) throws AxisFault {
		return getBean(RoomWebService.class).updateRoomWithModeration(SID,
				room_id, name, roomtypes_id, comment, numberOfPartizipants,
				ispublic, appointment, isDemoRoom, demoTime, isModeratedRoom);
	}

	public Long updateRoomWithModerationAndQuestions(String SID, Long room_id,
			String name, Long roomtypes_id, String comment,
			Long numberOfPartizipants, Boolean ispublic, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			Boolean allowUserQuestions) throws AxisFault {
		return getBean(RoomWebService.class).updateRoomWithModerationAndQuestions(
				SID, room_id, name, roomtypes_id, comment,
				numberOfPartizipants, ispublic, appointment, isDemoRoom,
				demoTime, isModeratedRoom, allowUserQuestions);
	}

	public Long updateRoomWithModerationQuestionsAudioTypeAndHideOptions(
			String SID, Long room_id, String name, Long roomtypes_id,
			String comment, Long numberOfPartizipants, Boolean ispublic,
			Boolean appointment, Boolean isDemoRoom, Integer demoTime,
			Boolean isModeratedRoom, Boolean allowUserQuestions,
			Boolean isAudioOnly, Boolean hideTopBar, Boolean hideChat,
			Boolean hideActivitiesAndActions, Boolean hideFilesExplorer,
			Boolean hideActionsMenu, Boolean hideScreenSharing,
			Boolean hideWhiteboard) throws AxisFault {
		return getBean(RoomWebService.class)
				.updateRoomWithModerationQuestionsAudioTypeAndHideOptions(SID,
						room_id, name, roomtypes_id, comment,
						numberOfPartizipants, ispublic, appointment,
						isDemoRoom, demoTime, isModeratedRoom,
						allowUserQuestions, isAudioOnly, hideTopBar, hideChat,
						hideActivitiesAndActions, hideFilesExplorer,
						hideActionsMenu, hideScreenSharing, hideWhiteboard);

	}

	public Long deleteRoom(String SID, long rooms_id) throws AxisFault {
		return getBean(RoomWebService.class).deleteRoom(SID, rooms_id);
	}

	public Boolean kickUser(String SID_Admin, Long room_id) throws AxisFault {
		return getBean(RoomWebService.class).kickUser(SID_Admin, room_id);
	}

	public Long addRoomWithModerationAndExternalType(String SID, String name,
			Long roomtypes_id, String comment, Long numberOfPartizipants,
			Boolean ispublic, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom, String externalRoomType)
			throws AxisFault {
		return getBean(RoomWebService.class).addRoomWithModerationAndExternalType(
				SID, name, roomtypes_id, comment, numberOfPartizipants,
				ispublic, appointment, isDemoRoom, demoTime, isModeratedRoom,
				externalRoomType);
	}

	public Long addRoomWithModerationExternalTypeAndAudioType(String SID,
			String name, Long roomtypes_id, String comment,
			Long numberOfPartizipants, Boolean ispublic, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			String externalRoomType, Boolean allowUserQuestions,
			Boolean isAudioOnly) throws AxisFault {
		return getBean(RoomWebService.class)
				.addRoomWithModerationExternalTypeAndAudioType(SID, name,
						roomtypes_id, comment, numberOfPartizipants, ispublic,
						appointment, isDemoRoom, demoTime, isModeratedRoom,
						externalRoomType, allowUserQuestions, isAudioOnly);
	}

	public Long addRoomWithModerationAndRecordingFlags(String SID, String name,
			Long roomtypes_id, String comment, Long numberOfPartizipants,
			Boolean ispublic, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom, String externalRoomType,
			Boolean allowUserQuestions, Boolean isAudioOnly,
			Boolean waitForRecording, Boolean allowRecording) throws AxisFault {
		return getBean(RoomWebService.class)
				.addRoomWithModerationAndRecordingFlags(SID, name,
						roomtypes_id, comment, numberOfPartizipants, ispublic,
						appointment, isDemoRoom, demoTime, isModeratedRoom,
						externalRoomType, allowUserQuestions, isAudioOnly,
						waitForRecording, allowRecording);
	}

	public Long addRoomWithModerationExternalTypeAndTopBarOption(String SID,
			String name, Long roomtypes_id, String comment,
			Long numberOfPartizipants, Boolean ispublic, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			String externalRoomType, Boolean allowUserQuestions,
			Boolean isAudioOnly, Boolean waitForRecording,
			Boolean allowRecording, Boolean hideTopBar) throws AxisFault {
		return getBean(RoomWebService.class)
				.addRoomWithModerationExternalTypeAndTopBarOption(SID, name,
						roomtypes_id, comment, numberOfPartizipants, ispublic,
						appointment, isDemoRoom, demoTime, isModeratedRoom,
						externalRoomType, allowUserQuestions, isAudioOnly,
						waitForRecording, allowRecording, hideTopBar);
	}

	public Long addRoomWithModerationQuestionsAudioTypeAndHideOptions(
			String SID, String name, Long roomtypes_id, String comment,
			Long numberOfPartizipants, Boolean ispublic, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			Boolean allowUserQuestions, Boolean isAudioOnly,
			Boolean hideTopBar, Boolean hideChat,
			Boolean hideActivitiesAndActions, Boolean hideFilesExplorer,
			Boolean hideActionsMenu, Boolean hideScreenSharing,
			Boolean hideWhiteboard) throws AxisFault {
		return getBean(RoomWebService.class).addRoomWithModerationQuestionsAudioTypeAndHideOptions(SID, name, roomtypes_id, comment, numberOfPartizipants, ispublic, appointment, isDemoRoom, demoTime, isModeratedRoom, allowUserQuestions, isAudioOnly, hideTopBar, hideChat, hideActivitiesAndActions, hideFilesExplorer, hideActionsMenu, hideScreenSharing, hideWhiteboard);
	}
	
	/**
	 * 
	 * Create a Invitation hash and optionally send it by mail the From to Date
	 * is as String as some SOAP libraries do not accept Date Objects in SOAP
	 * Calls Date is parsed as dd.mm.yyyy, time as hh:mm (don't forget the
	 * leading zero's)
	 * 
	 * @param SID
	 *            a valid Session Token
	 * @param username
	 *            the username of the User that he will get
	 * @param room_id
	 *            the conference room id of the invitation
	 * @param isPasswordProtected
	 *            if the invitation is password protected
	 * @param invitationpass
	 *            the password for accessing the conference room via the
	 *            invitation hash
	 * @param valid
	 *            the type of validation for the hash 1: endless, 2: from-to
	 *            period, 3: one-time
	 * @param validFromDate
	 *            Date in Format of dd.mm.yyyy only of interest if valid is type
	 *            2
	 * @param validFromTime
	 *            time in Format of hh:mm only of interest if valid is type 2
	 * @param validToDate
	 *            Date in Format of dd.mm.yyyy only of interest if valid is type
	 *            2
	 * @param validToTime
	 *            time in Format of hh:mm only of interest if valid is type 2
	 * @return a HASH value that can be made into a URL with
	 *         http://$OPENMEETINGS_HOST
	 *         :$PORT/openmeetings/?invitationHash="+invitationsHash;
	 * @throws AxisFault
	 */
	public String getInvitationHash(String SID, String username, Long room_id,
			Boolean isPasswordProtected, String invitationpass, Integer valid,
			String validFromDate, String validFromTime, String validToDate,
			String validToTime) throws AxisFault {
		return getBean(RoomWebService.class).getInvitationHash(SID, username,
				room_id, isPasswordProtected, invitationpass, valid,
				validFromDate, validFromTime, validToDate, validToTime);

	}

	/**
	 * 
	 * Create a Invitation hash and optionally send it by mail the From to Date
	 * is as String as some SOAP libraries do not accept Date Objects in SOAP
	 * Calls Date is parsed as dd.mm.yyyy, time as hh:mm (don't forget the
	 * leading zero's)
	 * 
	 * @param SID
	 *            a valid Session Token
	 * @param username
	 *            the username of the User that he will get
	 * @param firstname
	 *            the first name of the User that he will get
	 * @param lastname
	 *            the last name of the User that he will get
	 * @param room_id
	 *            the conference room id of the invitation
	 * @param isPasswordProtected
	 *            if the invitation is password protected
	 * @param invitationpass
	 *            the password for accessing the conference room via the
	 *            invitation hash
	 * @param valid
	 *            the type of validation for the hash 1: endless, 2: from-to
	 *            period, 3: one-time
	 * @param validFromDate
	 *            Date in Format of dd.mm.yyyy only of interest if valid is type
	 *            2
	 * @param validFromTime
	 *            time in Format of hh:mm only of interest if valid is type 2
	 * @param validToDate
	 *            Date in Format of dd.mm.yyyy only of interest if valid is type
	 *            2
	 * @param validToTime
	 *            time in Format of hh:mm only of interest if valid is type 2
	 * @return a HASH value that can be made into a URL with
	 *         http://$OPENMEETINGS_HOST
	 *         :$PORT/openmeetings/?invitationHash="+invitationsHash;
	 * @throws AxisFault
	 */
	public String getInvitationHashFullName(String SID, String username, String firstname, String lastname, Long room_id,
			Boolean isPasswordProtected, String invitationpass, Integer valid,
			String validFromDate, String validFromTime, String validToDate,
			String validToTime) throws AxisFault {
		return getBean(RoomWebService.class).getInvitationHashFullName(SID, username, firstname, lastname,
				room_id, isPasswordProtected, invitationpass, valid, validFromDate, validFromTime, validToDate, validToTime);

	}

	/**
	 * Create a Invitation hash and optionally send it by mail the From to Date
	 * is as String as some SOAP libraries do not accept Date Objects in SOAP
	 * Calls Date is parsed as dd.mm.yyyy, time as hh:mm (don't forget the
	 * leading zero's)
	 * 
	 * @param SID
	 *            a valid Session Token
	 * @param username
	 *            the Username of the User that he will get
	 * @param message
	 *            the Message in the Email Body send with the invitation if
	 *            sendMail is true
	 * @param email
	 *            the Email to send the invitation to if sendMail is true
	 * @param subject
	 *            the subject of the Email send with the invitation if sendMail
	 *            is true
	 * @param room_id
	 *            the conference room id of the invitation
	 * @param isPasswordProtected
	 *            if the invitation is password protected
	 * @param invitationpass
	 *            the password for accessing the conference room via the
	 *            invitation hash
	 * @param valid
	 *            the type of validation for the hash 1: endless, 2: from-to
	 *            period, 3: one-time
	 * @param validFromDate
	 *            Date in Format of dd.mm.yyyy only of interest if valid is type
	 *            2
	 * @param validFromTime
	 *            time in Format of hh:mm only of interest if valid is type 2
	 * @param validToDate
	 *            Date in Format of dd.mm.yyyy only of interest if valid is type
	 *            2
	 * @param validToTime
	 *            time in Format of hh:mm only of interest if valid is type 2
	 * @param language_id
	 *            the language id of the EMail that is send with the invitation
	 *            if sendMail is true
	 * @param sendMail
	 *            if sendMail is true then the RPC-Call will send the invitation
	 *            to the email
	 * @return a HASH value that can be made into a URL with
	 *         http://$OPENMEETINGS_HOST
	 *         :$PORT/openmeetings/?invitationHash="+invitationsHash;
	 * @throws AxisFault
	 */
	public String sendInvitationHash(String SID, String username,
			String message, String email, String subject,
			Long room_id, Boolean isPasswordProtected,
			String invitationpass, Integer valid, String validFromDate,
			String validFromTime, String validToDate, String validToTime,
			Long language_id, Boolean sendMail) throws AxisFault {
		return getBean(RoomWebService.class).sendInvitationHash(SID, username, message, email, subject, room_id,
				isPasswordProtected, invitationpass, valid, validFromDate, validFromTime, validToDate, validToTime, language_id, sendMail);
	}

	/**
	 * Create a Invitation hash and optionally send it by mail the From to Date
	 * is as String as some SOAP libraries do not accept Date Objects in SOAP
	 * Calls Date is parsed as dd.mm.yyyy, time as hh:mm (don't forget the
	 * leading zero's)
	 * 
	 * @param SID
	 *            a valid Session Token
	 * @param username
	 *            the Username of the User that he will get
	 * @param message
	 *            the Message in the Email Body send with the invitation if
	 *            sendMail is true
	 * @param email
	 *            the Email to send the invitation to if sendMail is true
	 * @param subject
	 *            the subject of the Email send with the invitation if sendMail
	 *            is true
	 * @param room_id
	 *            the conference room id of the invitation
	 * @param conferencedomain
	 *            the domain of the room (keep empty)
	 * @param isPasswordProtected
	 *            if the invitation is password protected
	 * @param invitationpass
	 *            the password for accessing the conference room via the
	 *            invitation hash
	 * @param valid
	 *            the type of validation for the hash 1: endless, 2: from-to
	 *            period, 3: one-time
	 * @param fromDate
	 *            Date as Date Object only of interest if valid is type 2
	 * @param toDate
	 *            Date as Date Object only of interest if valid is type 2
	 * @param language_id
	 *            the language id of the EMail that is send with the invitation
	 *            if sendMail is true
	 * @param sendMail
	 *            if sendMail is true then the RPC-Call will send the invitation
	 *            to the email
	 * @return a HASH value that can be made into a URL with
	 *         http://$OPENMEETINGS_HOST
	 *         :$PORT/openmeetings/?invitationHash="+invitationsHash;
	 * @throws AxisFault
	 */
	public String sendInvitationHashWithDateObject(String SID, String username,
			String message, String email, String subject,
			Long room_id, String conferencedomain, Boolean isPasswordProtected,
			String invitationpass, Integer valid, Date fromDate, Date toDate,
			Long language_id, Boolean sendMail) throws AxisFault {
		return getBean(RoomWebService.class).sendInvitationHashWithDateObject(SID, username, message, email, subject, room_id,
				conferencedomain, isPasswordProtected, invitationpass, valid, fromDate, toDate, language_id, sendMail);
	}

	public List<RoomReturn> getRoomsWithCurrentUsersByList(String SID,
			int start, int max, String orderby, boolean asc) throws AxisFault {
		return getBean(RoomWebService.class).getRoomsWithCurrentUsersByList(SID, start, max, orderby, asc);
	}

	public List<RoomReturn> getRoomsWithCurrentUsersByListAndType(String SID,
			int start, int max, String orderby, boolean asc,
			String externalRoomType) throws AxisFault {
		return getBean(RoomWebService.class).getRoomsWithCurrentUsersByListAndType(SID, start, max, orderby, asc, externalRoomType);
	}

	public Long addRoomWithModerationAndExternalTypeAndStartEnd(String SID,
			String name, Long roomtypes_id, String comment,
			Long numberOfPartizipants, Boolean ispublic, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			String externalRoomType, String validFromDate,
			String validFromTime, String validToDate, String validToTime,
			Boolean isPasswordProtected, String password, Long reminderTypeId,
			String redirectURL) throws AxisFault {
		return getBean(RoomWebService.class)
				.addRoomWithModerationAndExternalTypeAndStartEnd(SID, name,
						roomtypes_id, comment, numberOfPartizipants, ispublic,
						appointment, isDemoRoom, demoTime, isModeratedRoom,
						externalRoomType, validFromDate, validFromTime,
						validToDate, validToTime, isPasswordProtected,
						password, reminderTypeId, redirectURL);
	}

	public Long addMeetingMemberRemindToRoom(String SID, Long room_id,
			String firstname, String lastname, String email, String phone, Long language_id) throws AxisFault {
		return getBean(RoomWebService.class).addMeetingMemberRemindToRoom(SID,
				room_id, firstname, lastname, email, language_id);
	}

	public Long addExternalMeetingMemberRemindToRoom(String SID, Long room_id,
			String firstname, String lastname, String email, Long language_id, String jNameTimeZone, String invitorName)
			throws AxisFault {
		return getBean(RoomWebService.class).addExternalMeetingMemberRemindToRoom(
				SID, room_id, firstname, lastname, email, language_id, jNameTimeZone, invitorName);
	}

	public int closeRoom(String SID, Long room_id, Boolean status)
			throws AxisFault {
		return getBean(RoomWebService.class).closeRoom(SID, room_id, status);
	}

	public int modifyRoomParameter(String SID, Long room_id, String paramName, String paramValue) throws AxisFault {
		return getBean(RoomWebService.class).modifyRoomParameter(SID, room_id, paramName, paramValue);
	}
	
	public Long addRoomToOrg(String SID, Long rooms_id, Long organisation_id) throws AxisFault {
		return getBean(RoomWebService.class).addRoomToOrg(SID, rooms_id, organisation_id);
	}
}
