To create a JPA (Java Persistence API) app, do the following:
- create persistence.xml under WEB-INF/classes/META-INF in eclipse
- create POJO (AgentStatus in this example) with annotations
- create a JPA container in the code and call it refresh method
- ensure to have vaadin-jpacontainer-3.1.1.jar and hibernate-entitymanager-4.1.4.Final.jar
put persistence.xml under WEB-INF/classes/META-INF
<?xml version="1.0" encoding="UTF-8"?>
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="agent-status">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>net.mycompany.tps.blvd.domain.AgentStatus</class>
<properties>
<!--
<property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
-->
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.password" value="tm211"/>
<property name="hibernate.connection.url" value="jdbc:mysql://tpsdbs.mycompany.net/blvd"/>
<!-- <property name="hibernate.connection.url" value="jdbc:mysql://solo.mycompany.net/blvd"/> -->
<property name="hibernate.connection.username" value="tps_mon"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.timeout" value="300"/>
<property name="hibernate.c3p0.max_statememycompany" value="50"/>
<property name="hibernate.c3p0.idle_test_period" value="3000"/>
</properties>
</persistence-unit>
</persistence>
AgentStatus.java
package net.mycompany.tps.blvd.domain;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import net.mycompany.tps.blvd.dao.LaborTypeDao;
import net.mycompany.tps.blvd.dao.UsersDao;
import net.mycompany.tps.blvd.util.HibernateUtil;
@Entity
@Table(name="agent_status")
public class AgentStatus implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private int id;
@Transient
private String ani;
private String globalId;
@Column(name="last_call")
private Date lastCall;
@Column(name="login_time")
private Date loginTime;
@Column(name="login_type")
private String loginType; // one of 1ON1, GROUP, LOGGEDOFF, SUPER
private String paused; //one of TRUE/FALSE
private Date timestamp;
private String hostname;
private String channel;
public static String LOGIN_1ON1 = "1ON1";
public static String LOGIN_GROUP = "GROUP";
public static String LOGGED_OFF = "LOGGEDOFF";
public static String LOGIN_SUPER = "SUPER";
@Transient
private String agentName;
@Transient
private LaborType laborType;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Transient
public String getAni() {
return ani;
}
@Transient
public void setAni(String ani) {
this.ani = ani;
}
public String getGlobalId() {
return globalId;
}
public void setGlobalId(String globalId) {
this.globalId = globalId;
}
public Date getLastCall() {
return lastCall;
}
public void setLastCall(Date lastCall) {
this.lastCall = lastCall;
}
public Date getLoginTime() {
return loginTime;
}
public void setLoginTime(Date loginTime) {
this.loginTime = loginTime;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
public String getPaused() {
return paused;
}
public void setPaused(String paused) {
this.paused = paused;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
// end of getters and setters
public boolean isLoggedIn() {
return loginType != null && !loginType.equals(LOGGED_OFF);
}
public String getAgentName() {
if (id > 0) {
try {
Users user = new UsersDao().getById(id);
if (user != null) {
agentName = user.getLast() + ", " + user.getFirst();
laborType = new LaborTypeDao().getById(user.getLaborTypeId());
}
}
finally {
HibernateUtil.closeCurremycompanyession();
}
}
return agentName;
}
public String getHoldTimestamp() {
String holdTime = null;
long elapsedTime = Calendar.getInstance().getTimeInMillis() - getLastCall().getTime();
long secondInMillis = 1000;
long minuteInMillis = secondInMillis * 60;
long hourInMillis = minuteInMillis * 60;
long dayInMillis = hourInMillis * 24;
elapsedTime %= dayInMillis;
elapsedTime %= hourInMillis;
long elapsedMinute = elapsedTime / minuteInMillis;
elapsedTime %= minuteInMillis;
long elapsedSecond = elapsedTime / secondInMillis;
holdTime = String.format("%02d", elapsedMinute) + ":" + String.format("%02d", elapsedSecond);
return holdTime;
}
public String getAgentIcon() {
return null;
}
public String getTimestampAsHhmmss() {
if (timestamp != null)
return new SimpleDateFormat("HH:mm:ss").format(timestamp);
else
return "";
}
}
package net.mycompany.asteriskmon;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.annotation.WebServlet;
import net.mycompany.asterisk.model.Channel;
import net.mycompany.asteriskmon.misc.TpsAmProperties;
import net.mycompany.asteriskmon.util.MonitorProperties;
import net.mycompany.tps.ami.util.AmiEventCatcher;
import net.mycompany.tps.blvd.domain.AgentStatus;
import org.apache.log4j.Logger;
import org.asteriskjava.manager.ManagerConnection;
import org.asteriskjava.manager.ManagerEventListener;
import org.asteriskjava.manager.event.HangupEvent;
import org.asteriskjava.manager.event.ManagerEvent;
import org.asteriskjava.manager.event.NewExtenEvent;
import org.asteriskjava.manager.event.VarSetEvent;
import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.annotations.Push;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Title;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.data.Property;
import com.vaadin.data.util.BeanContainer;
import com.vaadin.data.util.BeanItem;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.JavaScript;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
@SuppressWarnings("serial")
@Title("TPS2 Monitor")
@Push
@Theme("mytheme")
public class TpsMonitorUI extends UI implements ManagerEventListener {
@WebServlet(value ={"/*"}, asyncSupported = true)
@VaadinServletConfiguration(heartbeatInterval = 60, productionMode = false, ui = TpsMonitorUI.class)
public static class Servlet extends VaadinServlet { }
private transient static Logger logger = Logger.getLogger(TpsMonitorUI.class);
BeanContainer<String, Channel> callers;
BeanContainer<String, Channel> agents;
BeanContainer<String, Summary> summaries;
private Table callerTable, agentTable, summaryTable;
private Map<String, Boolean> isWaitingForStatusEvemycompany = new HashMap<String,Boolean>();
private int agentsOneOnOne = 0;
private int callersOneOnOne = 0;
private static String TEXT_FIELD_WIDTH="200";
private Map<String,String> agentOnCallStateMap = new HashMap<String,String>();
private Map<String,String> agentGroupOnCallStateMap = new HashMap<String,String>();
private long lastUpdatedAgentStatus;
private static JPAContainer<AgentStatus> agentstatus;
private static List<AgentStatus> agentstatusList = new ArrayList<AgentStatus>(100);
@Override
protected void init(VaadinRequest request) {
initCallerTable();
initAgentTable();
initSummaryTable();
initLayout();
initAmiEventCatcher();
logger.info("Started UI: "+hashCode());
// Read the JS File and Process it
JavaScript.getCurrent().execute(readJsFile("refresh.js"));
agentstatus = JPAContainerFactory.make(AgentStatus.class, "agent-status");
}
private void initCallerTable() {
callers = new BeanContainer<String, Channel>(Channel.class);
callers.setBeanIdProperty("name");
callerTable = new Table("Callers", callers);
callerTable.setImmediate(true);
callerTable.setColumnHeader("timestampAsHhmmss", "Start");
callerTable.setColumnHeader("hostname", "Host");
callerTable.setVisibleColumns(new Object[] {"timestampAsHhmmss", "ani", "dnis", "product"});
callerTable.setSelectable(true);
callerTable.setPageLength(0); // to not have scrollbars
callerTable.addItemClickListener(new MonitorItemClickListener());
}
private void initAgentTable() {
agents = new BeanContainer<String, Channel>(Channel.class);
agents.setBeanIdProperty("name");
agentTable = new Table("AgentS", agents);
agentTable.setImmediate(true);
agentTable.setColumnHeader("agentIcon", "");
agentTable.setColumnHeader("agentName", "Agent Name");
agentTable.setColumnHeader("holdTimestamp", "Hold");
agentTable.setColumnHeader("timestampAsHhmmss", "Start");
agentTable.setColumnWidth("agentIcon", 60);
agentTable.setColumnHeader("hostname", "Host");
agentTable.setVisibleColumns(new Object[] {"agentIcon", "agentName", "holdTimestamp", "timestampAsHhmmss", "agent", "product", "hostname"});
agentTable.setSelectable(true);
agentTable.setPageLength(0); // to not have scrollbars
agentTable.setSortContainerPropertyId("agentName");
agentTable.setSortAscending(true);
agentTable.addGeneratedColumn("agentIcon", new IconColumnGenerator("laborType", "type", "paused"));
agentTable.addItemClickListener(new MonitorItemClickListener());
agentTable.setCellStyleGenerator(new Table.CellStyleGenerator() {
@Override
public String getStyle(Table source, Object itemId, Object propertyId) {
String itemString;
if (propertyId == null || itemId == null) return null;
Property prop = source.getContainerProperty(itemId, propertyId);
if (prop == null || prop.getValue() == null)
return "agent-value";
if (propertyId.equals("agent")) {
String agentstate = getAgentState((String)prop.getValue(), (String)itemId);
switch(agentstate) {
case Channel.STATE_ON_CALL:
return "agent-value stateOnCall";
case Channel.STATE_IDLE:
return "agent-value stateIdle";
case Channel.STATE_SUPERVISOR:
return "agent-value stateSupervisor";
default:
return "agent-value";
}
}
return "agent-value";
}
});
lastUpdatedAgentStatus = System.currentTimeMillis();
}
private void initSummaryTable() {
summaries = new BeanContainer<String, Summary>(Summary.class);
summaries.setBeanIdProperty("name");
Summary summary = new Summary();
summary.setName("summary");
summaries.addBean(summary);
summaryTable = new Table();
summaryTable.setContainerDataSource(summaries);
summaryTable.setImmediate(true);
summaryTable.setColumnHeader("callersInStories", "Stories");
summaryTable.setColumnHeader("callersInMessages", "Messages");
summaryTable.setColumnHeader("callersInDirectory", "Directory");
summaryTable.setColumnHeader("oneOnOne", "1on1");
summaryTable.setVisibleColumns(new Object[] {"channels", "oneOnOne", "group", "callersInStories", "callersInMessages", "callersInDirectory"});
summaryTable.setSelectable(true);
summaryTable.setColumnWidth("channels", 100);
summaryTable.setColumnWidth("oneOnOne", 150);
summaryTable.setColumnWidth("group", 120);
summaryTable.setCellStyleGenerator(new Table.CellStyleGenerator() {
@Override
public String getStyle(Table source, Object itemId, Object propertyId) {
String itemString;
logger.debug(source+","+itemId+","+propertyId);
if (propertyId == null || itemId == null) return null;
Property prop = source.getContainerProperty(itemId, propertyId);
if (propertyId.equals("channels")) {
int itemInt = (int) prop.getValue();
double usedChannelPercent = 0;
try {
usedChannelPercent = 100.0 * itemInt / MonitorProperties.maxChannels();
} catch (Exception e) {
logger.error("Failed to calculate used channels",e);
}
if (usedChannelPercent >= 85) return "summary-value red";
if (usedChannelPercent >= 75) return "summary-value orange";
}
if (propertyId.equals("oneOnOne")) {
if (agentsOneOnOne == 0 || callersOneOnOne == 0) return "summary-value red";
double callerToAgentRatio = 100.0 * callersOneOnOne / agentsOneOnOne;
if (callerToAgentRatio >= 85) return "summary-value red";
if (callerToAgentRatio >= 75) return "summary-value orange";
}
if (propertyId.equals("group")) {
itemString = (String) prop.getValue();
if (itemString == null) return null;
if (itemString.startsWith("0|")) return "summary-value red";
}
return "summary-value";
}
});
summaryTable.setPageLength(1); // to not have scrollbars
}
private void initLayout() {
VerticalLayout verticalLayout = new VerticalLayout();
// Top of vertical layout
verticalLayout.addComponent(summaryTable);
// Bottom of vertical layout
GridLayout channelsLayout = new GridLayout(2,1);
channelsLayout.addComponent(callerTable,0,0);
channelsLayout.addComponent(agentTable,1,0);
verticalLayout.addComponent(channelsLayout);
setContent(verticalLayout);
}
private void initAmiEventCatcher() {
for(Map.Entry<String, ManagerConnection> me : AmiEventCatcher.amiManagerConnectionMap.entrySet()) {
isWaitingForStatusEvemycompany.put(me.getKey(), true);
}
AmiEventCatcher.addEventListener(this);
AmiEventCatcher.sendStatusAction();
}
@Override
public void onManagerEvent(ManagerEvent event) {
String hostName = ((ManagerConnection)event.getSource()).getHostname();
String eventClassName = event.getClass().getSimpleName();
switch (eventClassName) {
case "DisconnectEvent":
handleEvemycompanyafely(event);
break;
case "ConnectEvent":
AmiEventCatcher.addEventListener(this);
break;
case "NewChannelEvent": // Create new channel objects
case "HangupEvent": // Remove channel objects
handleEvemycompanyafely(event);
updateSummaryTable();
break;
case "StatusEvent": // Response to StatusAction
if (isWaitingForStatusEvemycompany.get(hostName)) {
handleEvemycompanyafely(event);
}
break;
case "StatusCompleteEvent":
isWaitingForStatusEvemycompany.put(hostName, false);
updateSummaryTable();
break;
case "VarSetEvent":
updateVar(event);
updateSummaryTable();
break;
default:
break;
}
// Needs method because vaadin will not update correctly if we create separate thread to update UI
// Method is depended on AMI evemycompany
// Works in production but updates might be delayed in dev
try {
handleAgentStatusUpdate();
} catch (Exception e) {
logger.error("cannot run handleagentstatusupdate", e);
}
}
private void handleAgentStatusUpdate() throws Exception {
long elapsedTime = System.currentTimeMillis() - lastUpdatedAgentStatus;
if (elapsedTime >= TpsAmProperties.agentstatusManagerPollRate()) {
new refreshAgentS().run();
access(new Runnable() {
@Override
public void run() {
// Iterate all logged in AgentS
BeanItem<Channel> beanItem;
String agentId;
for (AgentStatus as : agentstatusList) {
beanItem = agents.getItem(as.getChannel());
if (beanItem != null) {
agentId = (String)beanItem.getItemProperty("agent").getValue();
// Agent Id must match
if ((agentId != null) && (agentId.equals(as.getId() + ""))) {
beanItem.getItemProperty("agentstatus").setValue(as);
beanItem.getItemProperty("agent").setValue(agentId); // Force screen to refresh
}
}
}
}
});
// Update last updated timestamp
lastUpdatedAgentStatus = System.currentTimeMillis();
}
}
private void handleEvemycompanyafely(final ManagerEvent event) {
final String eventClassName = event.getClass().getSimpleName();
access(new Runnable() {
@Override
public void run() {
switch (eventClassName) {
case "NewChannelEvent": // New call comes in
addNewChannel(event);
break;
case "StatusEvent": // Response to status action
addNewChannelForStatusEvent(event);
break;
case "HangupEvent": // Hangup on a channel
removeChannel(event);
break;
case "DisconnectEvent":
agentTable.removeAllItems();
callerTable.removeAllItems();
summaryTable.removeAllItems();
break;
}
}
});
}
private void updateVar(ManagerEvent event) {
final VarSetEvent vse = (VarSetEvent)event;
switch(vse.getVariable()) {
case "ACTIVE":
String value = vse.getValue();
if (value != null && value.equals("Agent-Login")) {
final BeanItem<Channel> channelBean = getChannelBean(callers, vse.getChannel());
if (channelBean != null) {
access(new Runnable() {
@Override
public void run() {
// Move from callers to agents table
callers.removeItem(vse.getChannel());
Channel bean = channelBean.getBean();
bean.setUserType(Channel.AGENT);
addChannelToTable(agents, bean);
}
});
}
}
break;
case "GLOBALID":
updateVar(vse, "globalId", false);
break;
case "AGENT":
// If agent value is null, we are disconnecting from an agent.
// Get callerChannel and cache the agent id as callersLastAgent
String agent=getAgentForCaller(vse.getValue(), vse.getChannel());
updateVar(vse, "agent", false); // Set caller channel agent var
updateAgentState(agent, vse.getValue(), vse.getChannel());
agentTable.sort(); // Name is populated after agent id is set
break;
case "ANI":
updateVar(vse, "ani", true);
break;
case "DNIS":
updateVar(vse, "dnis", true);
break;
case "PRODUCT":
String previousProduct=getProductForCaller(vse.getValue(), vse.getChannel());
updateVar(vse, "product", true);
if (previousProduct != null && previousProduct.endsWith("group")) // caller moved out of group
updateGroupAgentS();
break;
}
}
private void updateSummaryTable() {
access(new Runnable() {
@Override
public void run() {
BeanItem<Summary> summaryBean = getSummaryBean("summary");
if (summaryBean == null) {
Summary summary = new Summary();
summary.setName("summary");
summaries.addBean(summary);
summaryBean = getSummaryBean("summary");
}
Map<String,Integer> agentProductMap = new HashMap<String,Integer>();
Map<String,Integer> callerProductMap = new HashMap<String,Integer>();
for(int i=0; i < agents.size(); i++) {
String product = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("product").getValue();
agentProductMap.put(product, agentProductMap.get(product) == null ? 1 : 1 + agentProductMap.get(product));
}
for(int i=0; i < callers.size(); i++) {
String product = (String)callers.getItem(callers.getIdByIndex(i)).getItemProperty("product").getValue();
callerProductMap.put(product, callerProductMap.get(product) == null ? 1 : 1 + callerProductMap.get(product));
}
// Set only if changed
int totalChannels = callers.getItemIds().size() + agents.getItemIds().size();
if ((int)summaryBean.getItemProperty("channels").getValue() != totalChannels)
summaryBean.getItemProperty("channels").setValue(totalChannels);
agentsOneOnOne=agentProductMap.get("agent-login-1on1") == null ? 0 : agentProductMap.get("agent-login-1on1");
callersOneOnOne=callerProductMap.get("1on1") == null ? 0 : callerProductMap.get("1on1");
String oneOnOneStr = agentsOneOnOne + "|" + callersOneOnOne;
if (!oneOnOneStr.equals(summaryBean.getItemProperty("oneOnOne").getValue()))
summaryBean.getItemProperty("oneOnOne").setValue(oneOnOneStr);
int agentsInGroup = agentProductMap.get("agent-login-group") == null ? 0 : agentProductMap.get("agent-login-group");
int callersInGroup = callerProductMap.get("group") == null ? 0 : callerProductMap.get("group");
String groupStr = agentsInGroup + "|" + callersInGroup;
if (!groupStr.equals(summaryBean.getItemProperty("group").getValue()))
summaryBean.getItemProperty("group").setValue(groupStr);
int callersInStories = callerProductMap.get("stories") == null ? 0 : callerProductMap.get("stories");
if (callersInStories != (int)summaryBean.getItemProperty("callersInStories").getValue())
summaryBean.getItemProperty("callersInStories").setValue(callersInStories);
int callersInMessages = callerProductMap.get("messages") == null ? 0 : callerProductMap.get("messages");
if (callersInMessages != (int)summaryBean.getItemProperty("callersInMessages").getValue())
summaryBean.getItemProperty("callersInMessages").setValue(callersInMessages);
int callersInDirectory = callerProductMap.get("directory") == null ? 0 : callerProductMap.get("directory");
if (callersInDirectory != (int)summaryBean.getItemProperty("callersInDirectory").getValue())
summaryBean.getItemProperty("callersInDirectory").setValue(callersInDirectory);
};
});
}
private void updateVar(final VarSetEvent vse, final String beanVarName, boolean shouldUpdateScreen) {
final BeanItem<Channel> channelBean = getChannelBean(vse.getChannel());
if (channelBean != null) {// Make sure we have it
if (shouldUpdateScreen)
access(new Runnable() {
@Override
public void run() {
channelBean.getItemProperty(beanVarName).setValue(vse.getValue());
}
});
else
channelBean.getItemProperty(beanVarName).setValue(vse.getValue());
}
}
private void updateNewExten(ManagerEvent event) {
// Update caller context
final NewExtenEvent nee = (NewExtenEvent) event;
final BeanItem<Channel> channelBean = getChannelBean(nee.getChannel());
if (channelBean == null) return; // Make sure we have it
String currentValue = channelBean.getBean().getContext();
String newValue = nee.getContext();
if (!currentValue.equals(newValue)) {
access(new Runnable() {
@Override
public void run() {
channelBean.getItemProperty("context").setValue(nee.getContext());
}
});
}
}
private void removeChannel(ManagerEvent event) {
HangupEvent he = (HangupEvent) event;
if (!callers.removeItem(he.getChannel()))
agents.removeItem(he.getChannel());
}
private void addNewChannel(ManagerEvent event) {
Channel newChannel = new Channel(event);
if (!isValidChannel(newChannel) || newChannel.isFromTpsPeer())
return;
Object returnId = addChannelToTable(callers, newChannel);
if (returnId == null) logger.error("Failed during "+event);
}
private void addNewChannelForStatusEvent(ManagerEvent event) { // this method called upon browser refresh
Channel newChannel = new Channel(event);
if (!isValidChannel(newChannel) || newChannel.isFromTpsPeer() || newChannel.getDnis() == null || newChannel.getDnis().trim().equals(""))
return;
String hostName = ((ManagerConnection)event.getSource()).getHostname();
String active=AmiEventCatcher.getChannelVariable(newChannel.getName(), "ACTIVE", hostName);
Object returnId=null;
String product = newChannel.getProduct();
String agent = newChannel.getAgent();
if (active != null && active.equals("Agent-Login")) {
newChannel.setUserType(Channel.AGENT);
returnId = addChannelToTable(agents, newChannel);
if (agentOnCallStateMap.get(agent) != null) {
if (product.endsWith("supervisor") || product.endsWith("monitor"))
setAgentState(agent, Channel.STATE_SUPERVISOR);
else
setAgentState(agent, Channel.STATE_ON_CALL);
} else if (newChannel.getState().equals(Channel.STATE_NOT_LOGGED_IN)) {// only set idle on a not logged in default state
if (product.endsWith("group"))
setAgentState(agent, Channel.STATE_IDLE);
else if (product.endsWith("supervisor") || product.endsWith("monitor"))
setAgentState(agent, Channel.STATE_SUPERVISOR);
else
setAgentState(agent, Channel.STATE_IDLE);
}
if (agentGroupOnCallStateMap.get("0") != null) { // group agents have zero for agent id
markStateOfGroupAgentS(Channel.STATE_ON_CALL);
}
} else {
returnId = addChannelToTable(callers, newChannel);
if (agent != null) {
if (product.endsWith("group")) {
agentGroupOnCallStateMap.put(agent, Channel.STATE_ON_CALL); // we got caller event before the agent event
markStateOfGroupAgentS(Channel.STATE_ON_CALL);
} else {
agentOnCallStateMap.put(agent, Channel.STATE_ON_CALL); // we got caller event before the agent event
setAgentState(agent, Channel.STATE_ON_CALL);
}
}
}
if (returnId == null) {
logger.error("Adding to table returned null. event: "+event);
}
}
private BeanItem<Channel> getChannelBean(BeanContainer<String, Channel> beanContainer, String channel) {
BeanItem<Channel> channelBean = beanContainer.getItem(channel);
return channelBean;
}
private BeanItem<Channel> getChannelBean(String channel) {
BeanItem<Channel> channelBean = callers.getItem(channel);
if ( channelBean == null)
return agents.getItem(channel);
else
return channelBean;
}
private BeanItem<Summary> getSummaryBean(String name) {
return summaries.getItem(name);
}
@Override
public void detach() {
super.detach();
AmiEventCatcher.removeEventListener(this);
if (logger != null) logger.info("Detached UI: "+hashCode());
}
private Object addChannelToTable(BeanContainer<String, Channel> beanContainer, Channel newChannel) {
Object returnId = beanContainer.addBean(newChannel);
return returnId;
}
private boolean isValidChannel(Channel newChannel) {
// Check for DAHDI channel
if (newChannel.isStateReserved()) return false;
// Filter for whisper tags
if (newChannel.getName().contains("whispertag")) return false;
//if (newChannel.getAni() == null && newChannel.getDnis() == null) return false;
try {
// filter Canadian redirect after the FTC is denied access by the operator
if (newChannel.getName().contains(MonitorProperties.canadianRedirectIp()))
return false;
} catch (Exception e) {
logger.error("Canadian Redirect IP not set", e);
}
return true;
}
private String readJsFile(String jsFile) {
String basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
BufferedReader br=null;
StringBuffer javaScript= new StringBuffer();
try {
br= new BufferedReader(new FileReader(new File(basepath + "/" + jsFile)));
String line="";
while((line=br.readLine()) != null) {
javaScript.append(line);
}
} catch (Exception e) {
logger.error("can't read js file", e);
} finally {
try {
br.close();
} catch (Exception e) {}
}
String refreshInterval=null;
try {
refreshInterval = MonitorProperties.refreshSeconds();
} catch (Exception e) {
logger.warn("refresh interval not set in properties", e);
refreshInterval = "30";
}
return javaScript.toString().
replaceAll("refreshInterval", refreshInterval);
}
private FormLayout getChannelInfoLayout(Channel channelBean) {
FormLayout formLayout = new FormLayout();
TextField textField = new TextField("Channel Name");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getName());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("Agent");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getAgent());
textField.setReadOnly(true);
formLayout.addComponent(textField);
if (channelBean.getUserType() != null && channelBean.getUserType().equals(Channel.AGENT)) {
textField = new TextField("Agent Name");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getAgentName());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("Type");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getType());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("Labor Type");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getLaborType());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("State");
textField.setWidth(TEXT_FIELD_WIDTH);
String agentstate=getAgentState(channelBean.getAgent(), channelBean.getName());
textField.setValue(agentstate);
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("Last Call");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getAgentStatus().getLastCall().toString());
textField.setReadOnly(true);
formLayout.addComponent(textField);
}
textField = new TextField("Start");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getTimestamp() == null ? "" : channelBean.getTimestamp().toString());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("Global ID");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getGlobalId());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("ANI");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getAni());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("DNIS");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getDnis());
textField.setReadOnly(true);
formLayout.addComponent(textField);
textField = new TextField("Product");
textField.setWidth(TEXT_FIELD_WIDTH);
textField.setValue(channelBean.getProduct());
textField.setReadOnly(true);
formLayout.addComponent(textField);
if (channelBean.getProduct().equals("agent-login-1on1")) {
CheckBox checkbox = new CheckBox("Pause");
checkbox.setWidth(TEXT_FIELD_WIDTH);
checkbox.setValue(channelBean.getAgentPaused());
checkbox.setImmediate(true);
checkbox.addListener(new PauseClickListener(channelBean));
formLayout.addComponent(checkbox);
}
formLayout.setMargin(true);
return formLayout;
}
private void showChannelPopup(String channel) {
BeanItem<Channel> beanItem = getChannelBean(channel);
if (beanItem == null)
return;
Channel channelBean = beanItem.getBean();
FormLayout formLayout = getChannelInfoLayout(channelBean);
if (formLayout != null) {
Window channelPop = new Window("Channel Info for " + channelBean.getUserType());
channelPop.setModal(false);
channelPop.setClosable(true);
channelPop.setResizable(false);
channelPop.setDraggable(true);
channelPop.setContent(formLayout);
addWindow(channelPop);
}
}
class MonitorItemClickListener implements ItemClickListener {
public void itemClick(ItemClickEvent event) {
logger.info("event:" + event);
if (event.isDoubleClick()) {
String val = event.getItemId().toString();
if (val != null && !val.trim().equals("")) {
showChannelPopup(val);
}
}
}
}
private String getAgentState(String agent, String channelName) {
BeanItem<Channel> channelBean = getAgentChannelBeanItemForChannel(agent, channelName);
return channelBean == null ? Channel.STATE_NOT_LOGGED_IN : channelBean.getBean().getState();
}
private BeanItem<Channel> getAgentChannelBeanItemForChannel(String agent, String channelName) {
for(int i=0; i < agents.size(); i++) {
String agentId = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("agent").getValue();
String agentChannel = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("name").getValue();
if (agentId != null && agentId.equals(agent) && agentChannel != null && agentChannel.equals(channelName)) {
return agents.getItem(agents.getIdByIndex(i));
}
}
return null;
}
private BeanItem<Channel> getAgentChannelBeanItemForProduct(String agent, String product) {
for(int i=0; i < agents.size(); i++) {
String agentId = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("agent").getValue();
String agentProduct = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("product").getValue();
if (agentId != null && agentId.equals(agent) && agentProduct != null && agentProduct.endsWith(product)) {
return agents.getItem(agents.getIdByIndex(i));
}
}
return null;
}
private boolean isCallersInGroup() {
for(int i=0; i < callers.size(); i++) {
String product = (String)callers.getItem(callers.getIdByIndex(i)).getItemProperty("product").getValue();
if (product != null && product.endsWith("group")) {
return true;
}
}
return false;
}
private void setAgentState(final String agent, final String state) {
BeanItem<Channel> beanItem=null;
switch(state) {
case Channel.STATE_SUPERVISOR:
// assume supervisor has two products supervisor and monitor
beanItem = getAgentChannelBeanItemForProduct(agent, "supervisor");
if (beanItem == null)
beanItem = getAgentChannelBeanItemForProduct(agent, "monitor");
break;
default:
// assume an agent can only have 2 products: 1on1 and group
beanItem = getAgentChannelBeanItemForProduct(agent, "1on1");
if (beanItem == null)
beanItem = getAgentChannelBeanItemForProduct(agent, "group");
}
final BeanItem<Channel>channelBean = beanItem;
if (channelBean == null)
return;
access(new Runnable() {
@Override
public void run() {
channelBean.getItemProperty("state").setValue(state);
channelBean.getItemProperty("agent").setValue(agent);
}
});
}
private String getAgentForCaller(String eventVal, String eventChannel) {
if (eventVal == null) {
BeanItem<Channel> channelBeanItem = getChannelBean(callers, eventChannel);
if (channelBeanItem != null) {
Channel callerChannel = channelBeanItem.getBean();
return callerChannel.getAgent(); // cache the agent id returned from here
}
}
return null;
}
private void updateAgentState(String agent, String eventVal, String eventChannel) {
if (eventChannel.contains("whispertag"))
return;
if (agent != null) { // cached agent id is available
// caller disconnected from agent
setAgentState(agent, Channel.STATE_IDLE);
updateGroupAgentS();
} else {
// we don't have a cached agent id, use the eventVal for agent
BeanItem<Channel> channelBeanItem = getChannelBean(callers, eventChannel);
if (channelBeanItem != null) {
// the event came through caller's channel
// the caller is associated with the agent in eventVal
String product = channelBeanItem.getBean().getProduct();
if (product != null && product.contains("group")) {
markStateOfGroupAgentS(Channel.STATE_ON_CALL);
} else {
setAgentState(eventVal, Channel.STATE_ON_CALL);
}
} else {
// the event came through agent's channel
// agent login triggered the event
channelBeanItem = getChannelBean(agents, eventChannel);
if (channelBeanItem == null)
return;
Object product=channelBeanItem.getItemProperty("product").getValue();
if (product == null)
return;
if (product.toString().endsWith("group"))
updateGroupAgentS();
else if (product.toString().endsWith("supervisor") || product.toString().endsWith("monitor"))
setAgentState(eventVal, Channel.STATE_SUPERVISOR);
else if (!product.equals("idle")) //supervisor has this product idle
setAgentState(eventVal, Channel.STATE_IDLE);
}
}
}
private void markStateOfGroupAgentS(String state) {
//mark all beans with group as product to be on-call
for(int i=0; i < agents.size(); i++) {
String agentId = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("agent").getValue();
String agentProduct = (String)agents.getItem(agents.getIdByIndex(i)).getItemProperty("product").getValue();
if (agentProduct.endsWith("group")) {
setAgentState(agentId, state);
}
}
}
private void updateGroupAgentS() {
if (!isCallersInGroup()) { // do we have any callers in the group?
// mark all group agents as IDLE
markStateOfGroupAgentS(Channel.STATE_IDLE);
} else {
// mark all group agents as ONCALL
markStateOfGroupAgentS(Channel.STATE_ON_CALL);
}
}
private String getProductForCaller(String eventVal, String eventChannel) {
BeanItem<Channel> channelBeanItem = getChannelBean(callers, eventChannel);
if (channelBeanItem != null) {
Channel callerChannel = channelBeanItem.getBean();
return callerChannel.getProduct(); // cache the product returned from here
}
return null;
}
static class refreshAgentS {
public void run() {
agentstatus.refresh();
agentstatusList.clear();
for(int i=0; i < agentstatus.size(); i++) {
int iid = (Integer)agentstatus.getIdByIndex(i);
EntityItem<AgentStatus> item = agentstatus.getItem(iid);
AgentStatus agentstatus = (AgentStatus)item.getEntity();
if (agentstatus != null && agentstatus.getLoginType().equals(AgentStatus.LOGGED_OFF)) {
continue;
}
agentstatusList.add(agentstatus);
}
logger.info("In Refresh AgentS; size: " + agentstatusList.size() + " agentstatus size: " + agentstatus.size());
}
}
}
No comments:
Post a Comment