From 4a5a153471f793a7325f63400cbf199693859fe7 Mon Sep 17 00:00:00 2001
From: Gabriel Landais <glandais@kereval.com>
Date: Thu, 3 Mar 2011 13:18:02 +0000
Subject: [PATCH] Filtering messages based on step id

git-svn-id: https://scm.gforge.inria.fr/authscm/ycadoret/svn/gazelle/Maven/gazelle-proxy/trunk@20796 356b4b1a-1d2b-0410-8bf1-ffa24008f01e
---
 .../gazelle/proxy/dao/MessageFilterStep.java  | 275 +++++++++++++++---
 .../ihe/gazelle/proxy/enums/ChannelType.java  |   8 +-
 .../gazelle/proxy/action/MessagesBean.java    |  37 ++-
 .../net/ihe/gazelle/proxy/ws/ProxyForTM.java  |   2 +-
 .../src/main/webapp/messages.xhtml            |   2 +-
 .../src/main/webapp/searchMessageStep.xhtml   |  45 ++-
 6 files changed, 312 insertions(+), 57 deletions(-)

diff --git a/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/dao/MessageFilterStep.java b/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/dao/MessageFilterStep.java
index 30f4ca2a..31d98cd7 100644
--- a/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/dao/MessageFilterStep.java
+++ b/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/dao/MessageFilterStep.java
@@ -1,76 +1,270 @@
 package net.ihe.gazelle.proxy.dao;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import net.ihe.gazelle.proxy.model.tm.Configuration;
 import net.ihe.gazelle.proxy.model.tm.Step;
 import net.ihe.gazelle.proxy.model.tm.TestInstance;
 
+import org.apache.commons.lang.StringEscapeUtils;
 import org.hibernate.Criteria;
 import org.hibernate.criterion.Criterion;
-import org.hibernate.criterion.LogicalExpression;
 import org.hibernate.criterion.Restrictions;
 
 public class MessageFilterStep implements MessageFilter {
 
 	private Step step;
-	private boolean filterPath = true;
+	private boolean filterPathReceiver = true;
 	private boolean filterPathFrom = true;
 	private boolean filterDates = true;
 
+	public static String NEW_LINE = "\r\n";
+
 	public MessageFilterStep(Step step) {
 		super();
 		this.step = step;
 	}
 
-	public void appendFilters(Criteria criteria) {
-		TestInstance testInstance = step.getTestInstance();
+	private static interface Crit {
+		Criterion getCriterion();
+
+		List<String> asString();
+	}
+
+	private static class CritLogical implements Crit {
+
+		private boolean and;
+		private Crit[] crits;
+
+		public CritLogical(boolean and, Crit... crits) {
+			super();
+			this.crits = crits;
+			this.and = and;
+		}
+
+		public Criterion getCriterion() {
+			Criterion result = null;
+			for (Crit crit : crits) {
+				Criterion criterion = crit.getCriterion();
+				if (result == null) {
+					result = criterion;
+				} else {
+					if (and) {
+						result = Restrictions.and(result, criterion);
+					} else {
+						result = Restrictions.or(result, criterion);
+					}
+				}
+			}
+			return result;
+		}
+
+		public List<String> asString() {
+			String operator = "OR";
+			if (and) {
+				operator = "AND";
+			}
+
+			List<String> result = new ArrayList<String>();
+
+			for (int i = 0; i < crits.length; i++) {
+
+				List<String> critString = crits[i].asString();
+				if (critString.size() == 1) {
+					result.add("  " + critString.get(0));
+				} else {
+					result.add("(");
+					for (String crit1Line : critString) {
+						result.add("  " + crit1Line);
+					}
+					result.add(")");
+				}
+				if (i != crits.length - 1) {
+					result.add(operator);
+				}
+			}
+
+			return result;
+		}
+
+		@Override
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result + (and ? 1231 : 1237);
+			result = prime * result + Arrays.hashCode(crits);
+			return result;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (getClass() != obj.getClass())
+				return false;
+			CritLogical other = (CritLogical) obj;
+			if (and != other.and)
+				return false;
+			if (!Arrays.equals(crits, other.crits))
+				return false;
+			return true;
+		}
+
+	}
+
+	private static enum CritSimpleType {
+		EQ, GE, LE;
+	}
+
+	private static class CritSimple implements Crit {
+
+		private String field;
+		private String label;
+		private Object value;
+		private CritSimpleType type;
+
+		public CritSimple(String field, String label, Object value, CritSimpleType type) {
+			super();
+			this.field = field;
+			this.label = label;
+			this.value = value;
+			this.type = type;
+		}
+
+		public Criterion getCriterion() {
+			switch (type) {
+			case EQ:
+				return Restrictions.eq(field, value);
+			case GE:
+				return Restrictions.ge(field, value);
+			case LE:
+				return Restrictions.le(field, value);
+			}
+			return null;
+		}
+
+		public List<String> asString() {
+			String query = "";
+			switch (type) {
+			case EQ:
+				query = label + " " + value;
+				break;
+			case GE:
+				query = label + " > " + value;
+				break;
+			case LE:
+				query = label + " < " + value;
+				break;
+			}
+			return Collections.singletonList(query);
+		}
+
+		@Override
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result + ((field == null) ? 0 : field.hashCode());
+			result = prime * result + ((type == null) ? 0 : type.hashCode());
+			result = prime * result + ((value == null) ? 0 : value.hashCode());
+			return result;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (getClass() != obj.getClass())
+				return false;
+			CritSimple other = (CritSimple) obj;
+			if (field == null) {
+				if (other.field != null)
+					return false;
+			} else if (!field.equals(other.field))
+				return false;
+			if (type != other.type)
+				return false;
+			if (value == null) {
+				if (other.value != null)
+					return false;
+			} else if (!value.equals(other.value))
+				return false;
+			return true;
+		}
+
+	}
 
-		if (filterPath) {
-			List<Criterion> critSenders = new ArrayList<Criterion>();
-			List<Criterion> critReceivers = new ArrayList<Criterion>();
+	private Crit getFilter() {
+		List<Crit> criterions = new ArrayList<Crit>();
+		if (step != null) {
+			TestInstance testInstance = step.getTestInstance();
+
+			List<Crit> critSenders = new ArrayList<Crit>();
+			List<Crit> critReceivers = new ArrayList<Crit>();
 
 			List<Configuration> senders = step.getSenders();
 			for (Configuration configuration : senders) {
-				critSenders.add(Restrictions.eq("fromIP", configuration.getHost()));
+				critSenders.add(new CritSimple("fromIP", "from", configuration.getHost(), CritSimpleType.EQ));
 			}
 			List<Configuration> receivers = step.getReceivers();
 			for (Configuration configuration : receivers) {
-				critReceivers.add(Restrictions.eq("proxyPort", configuration.getProxyPort()));
+				critReceivers.add(new CritSimple("proxyPort", "proxy port", configuration.getProxyPort(),
+						CritSimpleType.EQ));
 			}
 
-			List<Criterion> paths = new ArrayList<Criterion>();
-			if (filterPathFrom) {
-				for (Criterion critSender : critSenders) {
-					for (Criterion critReceiver : critReceivers) {
-						LogicalExpression path = Restrictions.and(critSender, critReceiver);
+			Set<Crit> paths = new HashSet<Crit>();
+			if (filterPathFrom && filterPathReceiver) {
+				for (Crit critSender : critSenders) {
+					for (Crit critReceiver : critReceivers) {
+
+						Crit path = new CritLogical(true, critSender, critReceiver);
 						paths.add(path);
+
 					}
 				}
-			} else {
-				paths = critReceivers;
+			} else if (filterPathReceiver) {
+				paths = new HashSet<MessageFilterStep.Crit>(critReceivers);
+			} else if (filterPathFrom) {
+				paths = new HashSet<MessageFilterStep.Crit>(critSenders);
 			}
 
-			Criterion oneOfPath = null;
-			for (Criterion path : paths) {
-				if (oneOfPath == null) {
-					oneOfPath = path;
-				} else {
-					oneOfPath = Restrictions.or(oneOfPath, path);
-				}
+			if (paths.size() > 0) {
+				Crit[] pathsArray = paths.toArray(new Crit[paths.size()]);
+				Crit oneOfPath = new CritLogical(false, pathsArray);
+				criterions.add(oneOfPath);
+			}
+
+			if (filterDates) {
+				Date startDate = getStartDate(testInstance);
+				Date endDate = step.getDate();
+
+				criterions.add(new CritSimple("dateReceived", "date", startDate, CritSimpleType.GE));
+				criterions.add(new CritSimple("dateReceived", "date", endDate, CritSimpleType.LE));
 			}
+		}
 
-			criteria.add(oneOfPath);
+		Crit criterion = null;
+		if (criterions.size() > 0) {
+			Crit[] criterionsArray = criterions.toArray(new Crit[criterions.size()]);
+			criterion = new CritLogical(true, criterionsArray);
 		}
 
-		if (filterDates) {
-			Date startDate = getStartDate(testInstance);
-			Date endDate = step.getDate();
+		return criterion;
+	}
 
-			criteria.add(Restrictions.ge("dateReceived", startDate));
-			criteria.add(Restrictions.le("dateReceived", endDate));
+	public void appendFilters(Criteria criteria) {
+		Crit filter = getFilter();
+		if (filter != null) {
+			criteria.add(filter.getCriterion());
 		}
 	}
 
@@ -86,12 +280,12 @@ public class MessageFilterStep implements MessageFilter {
 		return startDate;
 	}
 
-	public boolean isFilterPath() {
-		return filterPath;
+	public boolean isFilterPathReceiver() {
+		return filterPathReceiver;
 	}
 
-	public void setFilterPath(boolean filterPath) {
-		this.filterPath = filterPath;
+	public void setFilterPathReceiver(boolean filterPathReceiver) {
+		this.filterPathReceiver = filterPathReceiver;
 	}
 
 	public boolean isFilterPathFrom() {
@@ -110,4 +304,19 @@ public class MessageFilterStep implements MessageFilter {
 		this.filterDates = filterDates;
 	}
 
+	public String getStepFilter() {
+		Crit criterion = getFilter();
+		if (criterion != null) {
+			StringBuilder sb = new StringBuilder();
+			List<String> criterionString = criterion.asString();
+			for (String string : criterionString) {
+				sb.append(string).append(NEW_LINE);
+			}
+			String result = StringEscapeUtils.escapeHtml(sb.toString());
+			return "<pre>" + result + "</pre>";
+		} else {
+			return "None";
+		}
+	}
+
 }
diff --git a/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/enums/ChannelType.java b/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/enums/ChannelType.java
index 9641fbe2..ae4bc8a7 100644
--- a/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/enums/ChannelType.java
+++ b/gazelle-proxy-datamodel/src/main/java/net/ihe/gazelle/proxy/enums/ChannelType.java
@@ -34,13 +34,13 @@ import net.ihe.gazelle.proxy.model.message.SyslogMessage;
 
 public enum ChannelType {
 
-	DICOM(DicomMessage.class, "dicomMessage"),
+	DICOM(DicomMessage.class, "DicomMessage"),
 
-	HL7(HL7Message.class, "hl7Message"),
+	HL7(HL7Message.class, "HL7Message"),
 
-	SYSLOG(SyslogMessage.class, "syslogMessage"),
+	SYSLOG(SyslogMessage.class, "SyslogMessage"),
 
-	HTTP(HTTPMessage.class, "httpMessage");
+	HTTP(HTTPMessage.class, "HTTPMessage");
 
 	private Class<? extends AbstractMessage> messageClass;
 	private String discriminator;
diff --git a/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/action/MessagesBean.java b/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/action/MessagesBean.java
index cab4aad5..5f4bd1a5 100644
--- a/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/action/MessagesBean.java
+++ b/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/action/MessagesBean.java
@@ -11,7 +11,6 @@ import javax.persistence.EntityManager;
 
 import net.ihe.gazelle.jsf.datatable.HibernateDataModel;
 import net.ihe.gazelle.proxy.action.dao.ProxyDAO;
-import net.ihe.gazelle.proxy.dao.MessageFilter;
 import net.ihe.gazelle.proxy.dao.MessageFilterStandard;
 import net.ihe.gazelle.proxy.dao.MessageFilterStep;
 import net.ihe.gazelle.proxy.enums.ChannelType;
@@ -38,15 +37,14 @@ public class MessagesBean {
 	private static final String TYPE_STANDARD = "STANDARD";
 
 	private transient HibernateMessageDataModel<AbstractMessage> messageDataModel;
-	private MessageFilter messageFilter;
 	private MessageFilterStandard messageFilterStandard;
 	private MessageFilterStep messageFilterStep;
 
 	@In
 	private EntityManager entityManager;
 
-	private String listType = null;
-	private Step step;
+	private String listType = TYPE_STANDARD;
+	private Step step = null;
 
 	public void clearFilter() {
 		messageFilterStandard.reset();
@@ -56,8 +54,7 @@ public class MessagesBean {
 	@Create
 	public void createModel() {
 		messageFilterStandard = new MessageFilterStandard();
-		messageFilter = messageFilterStandard;
-		messageFilterStep = null;
+		messageFilterStep = new MessageFilterStep(step);
 		rebuildDataModel();
 	}
 
@@ -126,14 +123,14 @@ public class MessagesBean {
 		return messageFilterStep.isFilterDates();
 	}
 
-	public boolean isFilterPath() {
-		return messageFilterStep.isFilterPath();
-	}
-
 	public boolean isFilterPathFrom() {
 		return messageFilterStep.isFilterPathFrom();
 	}
 
+	public String getStepFilter() {
+		return messageFilterStep.getStepFilter();
+	}
+
 	public String linkedLabel(AbstractMessage message) {
 		if (message instanceof HTTPMessage) {
 			HTTPMessage httpMessage = (HTTPMessage) message;
@@ -159,7 +156,12 @@ public class MessagesBean {
 	}
 
 	private void rebuildDataModel() {
-		messageDataModel = new HibernateMessageDataModel<AbstractMessage>(messageFilter);
+		if (listType.equals(TYPE_STANDARD)) {
+			messageDataModel = new HibernateMessageDataModel<AbstractMessage>(messageFilterStandard);
+		}
+		if (listType.equals(TYPE_TEST_STEP)) {
+			messageDataModel = new HibernateMessageDataModel<AbstractMessage>(messageFilterStep);
+		}
 	}
 
 	public String redirectToLinked(AbstractMessage message) {
@@ -211,9 +213,6 @@ public class MessagesBean {
 		messageFilterStep.setFilterDates(filterDates);
 	}
 
-	public void setFilterPath(boolean filterPath) {
-		messageFilterStep.setFilterPath(filterPath);
-	}
 
 	public void setFilterPathFrom(boolean filterPathFrom) {
 		messageFilterStep.setFilterPathFrom(filterPathFrom);
@@ -238,8 +237,6 @@ public class MessagesBean {
 				step = steps.get(0);
 			}
 			messageFilterStep = new MessageFilterStep(step);
-			messageFilter = messageFilterStep;
-			messageFilterStandard = null;
 
 			rebuildDataModel();
 		}
@@ -266,4 +263,12 @@ public class MessagesBean {
 		messageFilterStandard.setResponderPort(responderPort);
 	}
 
+	public boolean isFilterPathReceiver() {
+		return messageFilterStep.isFilterPathReceiver();
+	}
+
+	public void setFilterPathReceiver(boolean filterPathReceiver) {
+		messageFilterStep.setFilterPathReceiver(filterPathReceiver);
+	}
+
 }
diff --git a/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/ws/ProxyForTM.java b/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/ws/ProxyForTM.java
index 669173c2..988cf0c3 100644
--- a/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/ws/ProxyForTM.java
+++ b/gazelle-proxy-ejb/src/main/java/net/ihe/gazelle/proxy/ws/ProxyForTM.java
@@ -78,7 +78,7 @@ public class ProxyForTM implements IProxyForTM {
 		List<Configuration> stepConfigurations = new ArrayList<Configuration>();
 		for (Integer id : ids) {
 			Configuration stepConfiguration = getConfigurationByTmId(id, configurations);
-			if (stepConfiguration != null) {
+			if (stepConfiguration != null && stepConfiguration.getProxyPort() > 0) {
 				stepConfigurations.add(stepConfiguration);
 			}
 		}
diff --git a/gazelle-proxy-war/src/main/webapp/messages.xhtml b/gazelle-proxy-war/src/main/webapp/messages.xhtml
index 14545425..e70505b1 100644
--- a/gazelle-proxy-war/src/main/webapp/messages.xhtml
+++ b/gazelle-proxy-war/src/main/webapp/messages.xhtml
@@ -5,8 +5,8 @@
 	xmlns:h="http://java.sun.com/jsf/html"
 	xmlns:rich="http://richfaces.org/rich"
 	xmlns:a4j="http://richfaces.org/a4j" template="layout/template.xhtml">
-	#{messagesBean.setListType("STANDARD")}
 	<ui:define name="body">
+		#{messagesBean.setListType("STANDARD")}
 		<a4j:form>
 			<rich:simpleTogglePanel switchType="client" id="search"
 				label="Search criteria">
diff --git a/gazelle-proxy-war/src/main/webapp/searchMessageStep.xhtml b/gazelle-proxy-war/src/main/webapp/searchMessageStep.xhtml
index 8fa87c5e..1bbb1e14 100644
--- a/gazelle-proxy-war/src/main/webapp/searchMessageStep.xhtml
+++ b/gazelle-proxy-war/src/main/webapp/searchMessageStep.xhtml
@@ -5,10 +5,51 @@
 	xmlns:h="http://java.sun.com/jsf/html"
 	xmlns:rich="http://richfaces.org/rich"
 	xmlns:a4j="http://richfaces.org/a4j" template="layout/template.xhtml">
-	#{messagesBean.setListType("TEST_STEP")}
 	<ui:define name="body">
+		#{messagesBean.setListType("TEST_STEP")}
 		<a4j:form>
-			<ui:include src="messageList.xhtml" />
+			<rich:simpleTogglePanel switchType="client" id="search"
+				label="Search criteria">
+				<h:panelGrid columns="1">
+
+					<h:panelGrid columns="2">
+						<a4j:region selfRendered="true">
+							<h:selectBooleanCheckbox value="#{messagesBean.filterPathFrom}">
+								<a4j:support event="onchange" reRender="search,panelOfMessages" />
+							</h:selectBooleanCheckbox>
+						</a4j:region>
+						<h:outputText value="Filter message origin" />
+
+						<a4j:region selfRendered="true">
+							<h:selectBooleanCheckbox
+								value="#{messagesBean.filterPathReceiver}">
+								<a4j:support event="onchange" reRender="search,panelOfMessages" />
+							</h:selectBooleanCheckbox>
+						</a4j:region>
+						<h:outputText value="Filter message destination" />
+
+						<a4j:region selfRendered="true">
+							<h:selectBooleanCheckbox value="#{messagesBean.filterDates}">
+								<a4j:support event="onchange" reRender="search,panelOfMessages" />
+							</h:selectBooleanCheckbox>
+						</a4j:region>
+						<h:outputText value="Filter message dates" />
+					</h:panelGrid>
+
+					<h:panelGrid columns="2">
+						<h:outputText value="Filter :" />
+						<h:outputText style="font-family: monospace;" escape="false"
+							value="#{messagesBean.getStepFilter()}" />
+					</h:panelGrid>
+
+				</h:panelGrid>
+			</rich:simpleTogglePanel>
+
+			<rich:spacer height="5" />
+
+			<s:div id="panelOfMessages">
+				<ui:include src="messageList.xhtml" />
+			</s:div>
 		</a4j:form>
 	</ui:define>
 </ui:composition>
-- 
GitLab