package com.dianping.cat.consumer.transaction;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;

import com.dianping.cat.consumer.transaction.model.entity.TransactionName;
import com.dianping.cat.consumer.transaction.model.entity.TransactionReport;
import com.dianping.cat.consumer.transaction.model.entity.TransactionType;

public class TransactionReportUrlFilter extends com.dianping.cat.consumer.transaction.model.transform.DefaultXmlBuilder
      implements LogEnabled {

	private int m_maxItems = 200;

	private Logger m_logger;

	private void mergeName(TransactionName old, TransactionName other) {
		old.setTotalCount(old.getTotalCount() + other.getTotalCount());
		old.setFailCount(old.getFailCount() + other.getFailCount());

		if (other.getMin() < old.getMin()) {
			old.setMin(other.getMin());
		}

		if (other.getMax() > old.getMax()) {
			old.setMax(other.getMax());
		}

		old.setSum(old.getSum() + other.getSum());
		old.setSum2(old.getSum2() + other.getSum2());
		old.setLine95Value(0);
		if (old.getTotalCount() > 0) {
			old.setFailPercent(old.getFailCount() * 100.0 / old.getTotalCount());
			old.setAvg(old.getSum() / old.getTotalCount());
		}

		if (old.getSuccessMessageUrl() == null) {
			old.setSuccessMessageUrl(other.getSuccessMessageUrl());
		}

		if (old.getFailMessageUrl() == null) {
			old.setFailMessageUrl(other.getFailMessageUrl());
		}
	}

	@Override
	public void visitTransactionReport(TransactionReport transactionReport) {
		super.visitTransactionReport(transactionReport);
	}

	@Override
	public void visitType(TransactionType type) {
		if ("URL".equals(type.getId())) {
			Map<String, TransactionName> transactionNames = type.getNames();

			Set<String> names = transactionNames.keySet();
			Set<String> invalidates = new HashSet<String>();

			for (String temp : names) {
				int length = temp.length();

				for (int i = 0; i < length; i++) {
					//invalidate char
					if (temp.charAt(i) > 126 || temp.charAt(i) < 33) {
						invalidates.add(temp);
						continue;
					}
				}
			}

			for (String name : invalidates) {
				m_logger.error("remove invalidate url " + name);
				transactionNames.remove(name);
			}

			int size = transactionNames.size();

			if (size > m_maxItems) {
				List<TransactionName> all = new ArrayList<TransactionName>(transactionNames.values());

				Collections.sort(all, new TransactionNameCompator());
				type.getNames().clear();

				for (int i = 0; i < m_maxItems; i++) {
					type.addName(all.get(i));
				}

				TransactionName other = type.findOrCreateName("OTHERS");
				for (int i = m_maxItems; i < size; i++) {
					mergeName(other, all.get(i));
				}
			}
		}
		super.visitType(type);
	}

	public static class TransactionNameCompator implements Comparator<TransactionName> {

		@Override
		public int compare(TransactionName o1, TransactionName o2) {
			return (int) (o2.getTotalCount() - o1.getTotalCount());
		}
	}

	@Override
	public void enableLogging(Logger logger) {
		m_logger = logger;
	}
}
@@ -2108,16 +2108,17 @@
 %0A%09%09%09%09%09//
+ 
 invalida
@@ -2857,16 +2857,501 @@
 %09%09%7D%0A%09%09%09%7D
+%0A%0A%09%09%09List%3CString%3E toRemove = new ArrayList%3CString%3E();%0A%09%09%09TransactionName other = type.findOrCreateName(%22OTHERS%22);%0A%0A%09%09%09transactionNames = type.getNames();%0A%09%09%09names = transactionNames.keySet();%0A%09%09%09for (String temp : names) %7B%0A%09%09%09%09TransactionName tansactionName = transactionNames.get(temp);%0A%0A%09%09%09%09if (tansactionName.getTotalCount() == 1) %7B%0A%09%09%09%09%09toRemove.add(temp);%0A%09%09%09%09%09mergeName(other, tansactionName);%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%0A%09%09%09for (String temp : toRemove) %7B%0A%09%09%09%09transactionNames.remove(temp);%0A%09%09%09%7D
 %0A%09%09%7D%0A%09%09s
@@ -3372,16 +3372,19 @@
 (type);%0A
+%09%09%0A
 %09%7D%0A%0A%09pub

modify the url filter