/*
* � Copyright IBM Corp. 2013
*
* Licensed 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 com.ibm.domino.commons.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import lotus.domino.DateRange;
import lotus.domino.DateTime;
import lotus.domino.Directory;
import lotus.domino.DirectoryNavigator;
import lotus.domino.Name;
import lotus.domino.NotesException;
import lotus.domino.Session;
import com.ibm.commons.util.StringUtil;
import com.ibm.domino.commons.internal.Logger;
import com.ibm.domino.commons.util.BackendUtil;
/**
* Free rooms provider.
*
* <p>WARNING: You should never construct an instance of this directly.
* Get an instance of IFreeRoomsProvider from ProviderFactory.
*/
public class FreeRoomsProvider implements IFreeRoomsProvider {
private static Vector<String> s_lookupItems = lookupItems();
/* (non-Javadoc)
* @see com.ibm.domino.commons.model.IFreeRoomsProvider#getFreeRooms(java.lang.String, java.util.Date, java.util.Date, int)
*/
public List<Room> getFreeRooms(Session session, String site,
Date start, Date end, int capacity)
throws ModelException {
List<Room> rooms = null;
try {
// Get a list of matching rooms
List<Room> matches = findMatchingRooms(session, site, capacity);
// Reduce the list to the rooms that are free
if ( matches != null ) {
if ( matches.size() == 0 ) {
rooms = matches;
}
else {
rooms = findFreeRooms(session, matches, start, end);
}
}
}
catch (NotesException e) {
throw new ModelException("Error finding rooms matching the site and capacity", e); // $NLX-FreeRoomsProvider.Errorfindingroomsmatchingthesitea-1$
}
return rooms;
}
/**
* Given a list of rooms, find the ones that are free for a given range.
*
* @param session
* @param candidates
* @param start
* @param end
* @return
* @throws NotesException
*/
private List<Room> findFreeRooms(Session session, List<Room> candidates, Date start, Date end) throws NotesException {
List<Room> rooms = new ArrayList<Room>();
DateRange range = null;
Vector freetimes = null;
try {
DateTime dtStart = session.createDateTime(start);
DateTime dtEnd = session.createDateTime(end);
range = session.createDateRange();
range.setStartDateTime(dtStart);
range.setEndDateTime(dtEnd);
Iterator<Room> iterator = candidates.iterator();
while ( iterator.hasNext() ) {
if ( freetimes != null ) {
BackendUtil.safeRecycle(freetimes);
freetimes = null;
}
Room room = iterator.next();
String item = room.getEmailAddress();
if ( StringUtil.isEmpty(item) ) {
item = room.getDistinguishedName();
}
Vector<String> names = new Vector<String>(1);
names.addElement(item);
// Get the free time for this room
Logger.get().getLogger().fine("Searching free time for " + item); // $NON-NLS-1$
try {
freetimes = session.freeTimeSearch(range, 5, names, false);
}
catch (Throwable e) {
Logger.get().warn(e, "Exception thrown searching free time for {0}", item); // $NLW-FreeRoomsProvider.Exceptionthrownsearchingfreetimef-1$
}
if ( freetimes == null ) {
continue;
}
// Compare the start and end times of the first free block
DateRange freeRange = (DateRange)freetimes.get(0);
Date freeStart = freeRange.getStartDateTime().toJavaDate();
Date freeEnd = freeRange.getEndDateTime().toJavaDate();
if ( start.getTime() != freeStart.getTime() ||
end.getTime() != freeEnd.getTime() ) {
continue;
}
// It's completely free. Add it to the list.
rooms.add(room);
}
}
finally {
BackendUtil.safeRecycle(range);
BackendUtil.safeRecycle(freetimes);
}
return rooms;
}
/**
* Find the rooms in a given site with a minimum capacity.
*
* @param session
* @param site
* @param capacity
* @return
* @throws NotesException
* @throws ModelException
*/
private List<Room> findMatchingRooms(Session session, String site, int capacity)
throws NotesException, ModelException {
List<Room> rooms = new ArrayList<Room>();
Directory lookupDir = null;
try {
lookupDir = session.getDirectory();
Vector<String> vName = new Vector<String>();
vName.addElement(site);
Logger.get().getLogger().finest("Looking up rooms in site " + site); // $NON-NLS-1$
DirectoryNavigator dirNav = lookupDir.lookupNames("($Rooms)", vName, s_lookupItems, true); //$NON-NLS-1$
if( dirNav == null || dirNav.getCurrentMatches() == 0 ){
throw new ModelException("Site not found", ModelException.ERR_NOT_FOUND); // $NLX-FreeRoomsProvider.Sitenotfound-1$
}
boolean match = dirNav.findFirstMatch();
while (match) {
Vector<String> value = null;
// Get the room name
String fullName = null;
value = dirNav.getFirstItemValue();
if ( value != null && value.size() > 0 ) {
fullName = value.elementAt(0);
}
// Get the domain
String domain = null;
value = dirNav.getNextItemValue();
if ( value != null && value.size() > 0 ) {
domain = value.elementAt(0);
}
// Get the email address
String emailAddress = null;
value = dirNav.getNextItemValue();
if ( value != null && value.size() > 0 ) {
emailAddress = value.elementAt(0);
}
// Get the room capacity
Vector<Double> dValue = dirNav.getNextItemValue();
int roomCapacity = 0;
if ( dValue != null && dValue.size() > 0 ) {
roomCapacity = dValue.elementAt(0).intValue();
}
// Get the autoprocess type
String apType = null;
value = dirNav.getNextItemValue();
if ( value != null && value.size() > 0 ) {
apType = value.elementAt(0);
}
// Get the autoprocess user list
Vector<String> apUsers = dirNav.getNextItemValue();
// Check the room capacity
boolean skipRoom = false;
if ( roomCapacity < capacity ) {
skipRoom = true;
}
// Check the owner restrictions
if ( !skipRoom && "2".equals(apType) ) {
boolean userListed = false;
if ( apUsers != null && apUsers.size() > 0 ) {
String currentUser = session.getEffectiveUserName();
Iterator<String> iterator = apUsers.iterator();
while (iterator.hasNext()) {
String user = iterator.next();
if ( user.equals(currentUser) ) {
userListed = true;
break;
}
}
}
if ( !userListed ) {
skipRoom = true;
}
}
// Add or skip the room
Name name = session.createName(fullName);
if ( skipRoom ) {
Logger.get().getLogger().fine("Skipping room " + name.getAbbreviated() + " (" + roomCapacity + ")"); // $NON-NLS-1$
}
else {
Logger.get().getLogger().fine("Adding room " + name.getAbbreviated() + " (" + roomCapacity + ")"); // $NON-NLS-1$
Room room = new Room(name.getCommon(), name.getAbbreviated(), domain,
emailAddress, roomCapacity);
rooms.add(room);
}
match = dirNav.findNextMatch();
}
}
finally {
BackendUtil.safeRecycle(lookupDir);
}
return rooms;
}
private static Vector<String> lookupItems() {
Vector<String> lookupItems = new Vector<String>();
lookupItems.addElement("FullName"); //$NON-NLS-1$
lookupItems.addElement("MailDomain"); //$NON-NLS-1$
lookupItems.addElement("InternetAddress"); //$NON-NLS-1$
lookupItems.addElement("ResourceCapacity"); //$NON-NLS-1$
lookupItems.addElement("AutoprocessType"); //$NON-NLS-1$
lookupItems.addElement("AutoprocessUserList"); //$NON-NLS-1$
return lookupItems;
}
}