Java tutorial
/** * Copyright (c) 2008-2015 Geode Systems LLC * This Software is licensed under the Geode Systems RAMADDA License available in the source distribution in the file * ramadda_license.txt. The above copyright notice shall be included in all copies or substantial portions of the Software. */ /** * Copyright (c) 2008-2015 Geode Systems LLC * This Software is licensed under the Geode Systems RAMADDA License available in the source distribution in the file * ramadda_license.txt. The above copyright notice shall be included in all copies or substantial portions of the Software. */ package com.ramadda.plugins.investigation; import org.apache.commons.lang.text.StrTokenizer; import org.ramadda.plugins.db.*; import org.ramadda.repository.*; import org.ramadda.repository.output.*; import org.ramadda.repository.type.*; import org.ramadda.sql.Clause; import org.ramadda.util.HtmlUtils; import org.ramadda.util.Json; import org.ramadda.util.Utils; import org.ramadda.util.Utils; import org.w3c.dom.*; import ucar.unidata.util.IOUtil; import ucar.unidata.util.Misc; import ucar.unidata.util.StringUtil; import ucar.unidata.util.StringUtil; import ucar.unidata.util.TwoFacedObject; import ucar.unidata.xml.XmlUtil; import java.io.File; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.Hashtable; import java.util.List; /** * */ public class PhoneDbTypeHandler extends DbTypeHandler { /** _more_ */ public static final String VIEW_CALL_LISTING = "call.listing"; /** _more_ */ public static final String VIEW_CALL_GRAPH = "call.graph"; /** _more_ */ public static final String VIEW_CALL_GRAPH_DATA = "call.graphdata"; /** _more_ */ private static final String ARROW = " → "; /** _more_ */ public static final String ARG_DB_NAMES = "db.names"; /** _more_ */ public static final String ARG_IDS = "ids"; /** _more_ */ public static final String ARG_NUMBER = "number"; /** _more_ */ public static final String ARG_ANONYMIZE = "anonymize"; /** _more_ */ Column fromNumberColumn; /** _more_ */ Column toNumberColumn; /** _more_ */ Column fromNameColumn; /** _more_ */ Column toNameColumn; /** _more_ */ Column dateColumn; /** * _more_ * * * @param dbAdmin _more_ * @param repository _more_ * @param tableName _more_ * @param tableNode _more_ * @param desc _more_ * * @throws Exception _more_ */ public PhoneDbTypeHandler(DbAdminHandler dbAdmin, Repository repository, String tableName, Element tableNode, String desc) throws Exception { super(dbAdmin, repository, tableName, tableNode, desc); } /** * _more_ * * @param columnNodes _more_ * * @throws Exception _more_ */ public void init(List<Element> columnNodes) throws Exception { super.init(columnNodes); viewList.add(1, new TwoFacedObject("Call Listing", VIEW_CALL_LISTING)); viewList.add(1, new TwoFacedObject("Call Graph", VIEW_CALL_GRAPH)); } /** * _more_ * * @param request _more_ * @param entry _more_ * @param view _more_ * @param headerToks _more_ * @param baseUrl _more_ * @param addNext _more_ * * @throws Exception _more_ */ @Override public void addHeaderItems(Request request, Entry entry, String view, List<String> headerToks, String baseUrl, boolean[] addNext) throws Exception { super.addHeaderItems(request, entry, view, headerToks, baseUrl, addNext); if (view.equals(VIEW_CALL_LISTING)) { addNext[0] = true; headerToks.add(HtmlUtils.b(msg("Call Listing"))); } else { headerToks.add( HtmlUtils.href(baseUrl + "&" + ARG_DB_VIEW + "=" + VIEW_CALL_LISTING, msg("Call Listing"))); } if (view.equals(VIEW_CALL_GRAPH)) { addNext[0] = true; headerToks.add(HtmlUtils.b(msg("Call Graph"))); } else { headerToks.add(HtmlUtils.href(baseUrl + "&" + ARG_DB_VIEW + "=" + VIEW_CALL_GRAPH, msg("Call Graph"))); } } /** * _more_ * * @param request _more_ * @param entry _more_ * @param sb _more_ * @param column _more_ * @param values _more_ * @param sdf _more_ * * @throws Exception _more_ */ @Override public void formatTableValue(Request request, Entry entry, Appendable sb, Column column, Object[] values, SimpleDateFormat sdf) throws Exception { if (column.equals(fromNumberColumn) || column.equals(toNumberColumn)) { Utils.append(sb, formatNumber(column.getString(values))); } else { super.formatTableValue(request, entry, sb, column, values, sdf); } } /** * _more_ * * @param n _more_ * * @return _more_ */ public String formatNumber(String n) { n = n.trim(); if (n.length() != 10) { return n; } return n.substring(0, 3) + "-" + n.substring(3, 6) + "-" + n.substring(6); } /** * _more_ * * @param request _more_ * @param entry _more_ * @param formBuffer _more_ * * @throws Exception _more_ */ @Override public void addToEditForm(Request request, Entry entry, Appendable formBuffer) throws Exception { super.addToEditForm(request, entry, formBuffer); Utils.append(formBuffer, HtmlUtils.row(HtmlUtils.colspan("Enter numbers and names", 2))); Utils.append(formBuffer, HtmlUtils.formEntry(msgLabel("Numbers and names"), HtmlUtils.textArea(ARG_DB_NAMES, "#number=name\n#e.g.:\n#303-555-1212= some name\n", 8, 50))); } /** * _more_ * * @param request _more_ * @param entry _more_ * @param parent _more_ * @param newEntry _more_ * * @throws Exception _more_ */ public void initializeEntryFromForm(Request request, Entry entry, Entry parent, boolean newEntry) throws Exception { super.initializeEntryFromForm(request, entry, parent, newEntry); if (newEntry) { return; } List<String[]> numberToName = new ArrayList<String[]>(); for (String line : StringUtil.split(request.getString(ARG_DB_NAMES, ""), "\n", true, true)) { line = line.trim(); if (line.startsWith("#")) { continue; } List<String> numberAndName = StringUtil.splitUpTo(line, "=", 2); if (numberAndName.size() < 2) { continue; } String number = numberAndName.get(0).trim(); String name = numberAndName.get(1).trim(); number = cleanUpNumber(number); if ((number.length() > 0) && (name.length() > 0)) { numberToName.add(new String[] { number, name }); } } if (numberToName.size() > 0) { for (String[] pair : numberToName) { String number = pair[0]; String name = pair[1]; List<Clause> fromWhere = new ArrayList<Clause>(); fromWhere.add(Clause.eq(COL_ID, entry.getId())); fromWhere.add(Clause.eq(fromNumberColumn.getName(), number)); Clause fromClause = Clause.and(fromWhere); getDatabaseManager().update(tableHandler.getTableName(), fromClause, new String[] { getFromNameColumn() }, new Object[] { name }); List<Clause> toWhere = new ArrayList<Clause>(); toWhere.add(Clause.eq(COL_ID, entry.getId())); toWhere.add(Clause.eq(toNumberColumn.getName(), number)); Clause toClause = Clause.and(toWhere); getDatabaseManager().update(tableHandler.getTableName(), toClause, new String[] { getToNameColumn() }, new Object[] { name }); } } } /** * _more_ * * @param number _more_ * * @return _more_ */ public String cleanUpNumber(String number) { return number; } /** * _more_ * * @return _more_ */ public String getFromNameColumn() { return "from_name"; } /** * _more_ * * @return _more_ */ public String getToNameColumn() { return "to_name"; } /** * _more_ * * @param request _more_ * @param entry _more_ * * @return _more_ * * @throws Exception _more_ */ public Result getHtmlDisplay(Request request, Entry entry) throws Exception { String view = request.getString(ARG_DB_VIEW, VIEW_TABLE); if (view.equals(VIEW_CALL_GRAPH_DATA)) { return handleCallGraphData(request, entry); } return super.getHtmlDisplay(request, entry); } /** _more_ */ private int cnt = 0; /** * _more_ * * @param request _more_ * @param entry _more_ * @param valueList _more_ * @param fromSearch _more_ * * @return _more_ * * @throws Exception _more_ */ public Result handleCallGraphPage(Request request, Entry entry, List<Object[]> valueList, boolean fromSearch) throws Exception { StringBuilder sb = new StringBuilder(); addViewHeader(request, entry, sb, VIEW_CALL_GRAPH, valueList.size(), fromSearch); sb.append("\n\n"); StringBuilder js = new StringBuilder(); GraphOutputHandler goh = getWikiManager().getGraphOutputHandler(); int width = 800; int height = 500; String id = goh.addPrefixHtml(sb, js, width, height); List<String> nodes = new ArrayList<String>(); List<String> links = new ArrayList<String>(); getNodesAndLinks(request, entry, valueList, nodes, links); goh.addSuffixHtml(sb, js, id, nodes, links, width, height); Result result = new Result(msg("Graph"), sb); return result; } /** * _more_ * * @param request _more_ * @param entry _more_ * @param valueList _more_ * @param nodes _more_ * @param links _more_ * * @throws Exception _more_ */ private void getNodesAndLinks(Request request, Entry entry, List<Object[]> valueList, List<String> nodes, List<String> links) throws Exception { GraphOutputHandler goh = getWikiManager().getGraphOutputHandler(); String iconUrl = getEntryIcon(request, entry); HashSet<String> seen = new HashSet<String>(); Hashtable<String, Integer> count = new Hashtable<String, Integer>(); for (int i = 0; i < valueList.size(); i++) { Object[] values = valueList.get(i); String fromNumber = fromNumberColumn.getString(values); String toNumber = toNumberColumn.getString(values); String entryUrl = request.entryUrl(getRepository().URL_ENTRY_SHOW, entry); StringBuilder row = new StringBuilder(); if (!seen.contains(fromNumber)) { String searchUrl = HtmlUtils.url(request.makeUrl(getRepository().URL_ENTRY_SHOW), new String[] { ARG_ENTRYID, entry.getId(), ARG_DB_SEARCH, "true", getSearchUrlArgument(fromNumberColumn), fromNumber }); nodes.add(Json.map(new String[] { goh.ATTR_NAME, formatNumber(fromNumber), goh.ATTR_LABEL, fromNameColumn.getString(values), goh.ATTR_NODEID, fromNumber, goh.ATTR_URL, searchUrl, goh.ATTR_GRAPHURL, getDataUrl(request, entry, fromNumber), goh.ATTR_ICON, iconUrl }, true)); seen.add(fromNumber); } if (!seen.contains(toNumber)) { String searchUrl = HtmlUtils.url(request.makeUrl(getRepository().URL_ENTRY_SHOW), new String[] { ARG_ENTRYID, entry.getId(), ARG_DB_SEARCH, "true", getSearchUrlArgument(fromNumberColumn), fromNumber }); nodes.add(Json.map( new String[] { goh.ATTR_NAME, formatNumber(toNumber), goh.ATTR_LABEL, toNameColumn.getString(values), goh.ATTR_NODEID, toNumber, goh.ATTR_URL, searchUrl, goh.ATTR_GRAPHURL, getDataUrl(request, entry, toNumber), goh.ATTR_ICON, iconUrl }, true)); seen.add(toNumber); } links.add(Json.map(new String[] { goh.ATTR_SOURCE_ID, fromNumber, goh.ATTR_TARGET_ID, toNumber, goh.ATTR_TITLE, "" }, true)); } } /** * _more_ * * @param request _more_ * @param entry _more_ * @param number _more_ * * @return _more_ */ private String getDataUrl(Request request, Entry entry, String number) { return HtmlUtils.url(request.makeUrl(getRepository().URL_ENTRY_SHOW), new String[] { ARG_ENTRYID, entry.getId(), ARG_DB_VIEW, VIEW_CALL_GRAPH_DATA, ARG_NUMBER, number }); } /** * _more_ * * @param request _more_ * @param entry _more_ * * @return _more_ * * @throws Exception _more_ */ public Result handleCallGraphData(Request request, Entry entry) throws Exception { StringBuilder sb = new StringBuilder(); GraphOutputHandler goh = getWikiManager().getGraphOutputHandler(); String number = request.getString(ARG_NUMBER, ""); List<Clause> where; where = new ArrayList<Clause>(); where.add(Clause.eq(COL_ID, entry.getId())); where.add(Clause.or(Clause.eq(fromNumberColumn.getFullName(), number), Clause.eq(toNumberColumn.getFullName(), number))); List<Object[]> values = readValues(request, entry, Clause.and(where)); List<String> nodes = new ArrayList<String>(); List<String> links = new ArrayList<String>(); getNodesAndLinks(request, entry, values, nodes, links); StringBuilder json = new StringBuilder(); json.append("{\n"); json.append("\"nodes\":[\n"); json.append(StringUtil.join(",", nodes)); json.append("]"); json.append(",\n"); json.append("\"links\":[\n"); json.append(StringUtil.join(",", links)); json.append("]\n"); json.append("}\n"); return new Result(BLANK, json, getRepository().getMimeTypeFromSuffix(".json")); } /** * _more_ * * @param request _more_ * @param entry _more_ * @param view _more_ * @param action _more_ * @param fromSearch _more_ * @param valueList _more_ * * @return _more_ * * @throws Exception _more_ */ public Result makeListResults(Request request, Entry entry, String view, String action, boolean fromSearch, List<Object[]> valueList) throws Exception { if (view.equals(VIEW_CALL_LISTING)) { return handleCallListing(request, entry, valueList, fromSearch); } if (view.equals(VIEW_CALL_GRAPH)) { return handleCallGraphPage(request, entry, valueList, fromSearch); } return super.makeListResults(request, entry, view, action, fromSearch, valueList); } /** * _more_ * * @param request _more_ * @param entry _more_ * @param valueList _more_ * @param fromSearch _more_ * * @return _more_ * * @throws Exception _more_ */ public Result handleCallListing(Request request, Entry entry, List<Object[]> valueList, boolean fromSearch) throws Exception { Hashtable<String, Number> numberMap = new Hashtable<String, Number>(); List<Number> numbers = new ArrayList<Number>(); StringBuilder sb = new StringBuilder(); addViewHeader(request, entry, sb, VIEW_CALL_LISTING, valueList.size(), fromSearch); for (Object[] tuple : valueList) { String fromNumber = fromNumberColumn.getString(tuple); Number from = numberMap.get(fromNumber); if (from == null) { from = new Number(fromNumber, fromNameColumn.getString(tuple)); numbers.add(from); numberMap.put(from.number, from); } String toNumber = toNumberColumn.getString(tuple); Number to = numberMap.get(toNumber); if (to == null) { to = new Number(toNumber, toNameColumn.getString(tuple)); numbers.add(to); numberMap.put(to.number, to); } String date = dateColumn.getString(tuple); from.addOutbound(to, tuple); to.addInbound(from, tuple); } SimpleDateFormat sdf = getDateFormat(entry); Collections.sort(numbers); for (Number n : numbers) { //Only show numbers with outbounds if ((n.outbound.size() <= 1) && (n.inbound.size() <= 1)) { continue; } sb.append(HtmlUtils.p()); sb.append(HtmlUtils.div(getTitle(n), HtmlUtils.cssClass("ramadda-heading-1"))); if (n.outbound.size() > 0) { sb.append(HtmlUtils.open(HtmlUtils.TAG_DIV, HtmlUtils.style("margin-top:0px;margin-left:20px;"))); StringBuilder numberSB = new StringBuilder("<table cellspacing=5 width=100%>"); for (Number outbound : n.getSortedOutbound()) { numberSB.append("<tr valign=top><td width=10%>"); String searchUrl = HtmlUtils.url(request.makeUrl(getRepository().URL_ENTRY_SHOW), new String[] { ARG_ENTRYID, entry.getId(), ARG_DB_SEARCH, "true", getSearchUrlArgument(fromNumberColumn), n.number, toNumberColumn.getSearchArg(), outbound.number, }); numberSB.append(HtmlUtils.href(searchUrl, getTitle(outbound))); numberSB.append("</td>"); List<Object[]> calls = n.getOutboundCalls(outbound); StringBuilder callSB = new StringBuilder(); for (Object[] values : calls) { StringBuilder dateSB = new StringBuilder(); dateColumn.formatValue(entry, dateSB, Column.OUTPUT_HTML, values, sdf); StringBuilder html = new StringBuilder(); getHtml(request, html, entry, values); callSB.append(HtmlUtils.makeShowHideBlock(dateSB.toString(), HtmlUtils.insetLeft( HtmlUtils.div(html.toString(), HtmlUtils.cssClass("ramadda-popup-box")), 10), false)); } numberSB.append("<td width=5% align=right>"); numberSB.append(calls.size()); numberSB.append("</td><td width=85%>"); numberSB.append(HtmlUtils.makeShowHideBlock("Details", HtmlUtils.insetLeft(callSB.toString(), 10), false)); numberSB.append("</td></tr>"); } numberSB.append("</table>"); sb.append(HtmlUtils.makeShowHideBlock("Outbound", HtmlUtils.insetLeft(numberSB.toString(), 10), true)); sb.append(HtmlUtils.close(HtmlUtils.TAG_DIV)); } if (n.inbound.size() > 0) { sb.append(HtmlUtils.open(HtmlUtils.TAG_DIV, HtmlUtils.style("margin-top:0px;margin-left:20px;"))); StringBuilder numberSB = new StringBuilder("<table cellspacing=5 width=100%>"); for (Number inbound : n.getSortedInbound()) { numberSB.append("<tr valign=top><td width=10%>"); String searchUrl = HtmlUtils.url(request.makeUrl(getRepository().URL_ENTRY_SHOW), new String[] { ARG_ENTRYID, entry.getId(), ARG_DB_SEARCH, "true", getSearchUrlArgument(fromNumberColumn), n.number, toNumberColumn.getSearchArg(), inbound.number, }); numberSB.append(HtmlUtils.href(searchUrl, getTitle(inbound))); numberSB.append("</td>"); List<Object[]> calls = n.getInboundCalls(inbound); StringBuilder callSB = new StringBuilder(); for (Object[] values : calls) { StringBuilder dateSB = new StringBuilder(); dateColumn.formatValue(entry, dateSB, Column.OUTPUT_HTML, values, sdf); StringBuilder html = new StringBuilder(); getHtml(request, html, entry, values); callSB.append(HtmlUtils.makeShowHideBlock(dateSB.toString(), HtmlUtils.insetLeft( HtmlUtils.div(html.toString(), HtmlUtils.cssClass("ramadda-popup-box")), 10), false)); } numberSB.append("<td width=5% align=right>"); numberSB.append(calls.size()); numberSB.append("</td><td width=85%>"); numberSB.append(HtmlUtils.makeShowHideBlock("Details", HtmlUtils.insetLeft(callSB.toString(), 10), false)); numberSB.append("</td></tr>"); } numberSB.append("</table>"); sb.append( HtmlUtils.makeShowHideBlock("Inbound", HtmlUtils.insetLeft(numberSB.toString(), 10), true)); sb.append(HtmlUtils.close(HtmlUtils.TAG_DIV)); } } return new Result(getTitle(request, entry), sb); } /** * _more_ * * @param n _more_ * * @return _more_ */ private String getTitle(Number n) { if (Utils.stringDefined(n.name)) { return n.name + " (" + formatNumber(n.number) + ")"; } return formatNumber(n.number); } /** * * @param entry _more_ * @param values _more_ * @param sdf _more_ * * @return _more_ * * @throws Exception _more_ */ @Override public String getMapLabel(Entry entry, Object[] values, SimpleDateFormat sdf) throws Exception { StringBuilder sb = new StringBuilder(); dateColumn.formatValue(entry, sb, Column.OUTPUT_HTML, values, sdf); sb.append(": "); sb.append(formatNumber(fromNumberColumn.getString(values))); sb.append(ARROW); sb.append(formatNumber(toNumberColumn.getString(values))); return sb.toString(); } /** * _more_ * * @param entry _more_ * @param values _more_ * @param sdf _more_ * * @return _more_ * * @throws Exception _more_ */ @Override public String getKmlLabel(Entry entry, Object[] values, SimpleDateFormat sdf) throws Exception { StringBuilder sb = new StringBuilder(); // dateColumn.formatValue(entry, sb, Column.OUTPUT_HTML, values, sdf); // sb.append(": "); sb.append(formatNumber(fromNumberColumn.getString(values))); sb.append(" - "); sb.append(formatNumber(toNumberColumn.getString(values))); return sb.toString(); } /** * _more_ * * @return _more_ */ @Override public String getDefaultDateFormatString() { return "yyyy/MM/dd HH:mm z"; } /** * _more_ * * @param entry _more_ * @param values _more_ * @param sdf _more_ * * @return _more_ * * @throws Exception _more_ */ @Override public String getCalendarLabel(Entry entry, Object[] values, SimpleDateFormat sdf) throws Exception { SimpleDateFormat timesdf = new SimpleDateFormat("HH:mm"); timesdf.setTimeZone(sdf.getTimeZone()); StringBuilder sb = new StringBuilder(); dateColumn.formatValue(entry, sb, Column.OUTPUT_HTML, values, timesdf); sb.append(": "); sb.append(formatNumber(fromNumberColumn.getString(values))); sb.append(ARROW); sb.append(formatNumber(toNumberColumn.getString(values))); return sb.toString(); } /** * _more_ * * @param request _more_ * @param entry _more_ * @param sb _more_ * @param formBuffer _more_ */ @Override public void createBulkForm(Request request, Entry entry, Appendable sb, Appendable formBuffer) { StringBuilder bulkSB = new StringBuilder(); makeForm(request, entry, bulkSB); StringBuilder bulkButtons = new StringBuilder(); bulkButtons.append(HtmlUtils.submit(msg("Create entries"), ARG_DB_CREATE)); bulkButtons.append(HtmlUtils.submit(msg("Cancel"), ARG_DB_LIST)); bulkSB.append(HtmlUtils.p()); bulkSB.append(header("Upload a call log file")); bulkSB.append(HtmlUtils.p()); bulkSB.append(bulkButtons); bulkSB.append(HtmlUtils.p()); bulkSB.append(msgLabel("File")); bulkSB.append(HtmlUtils.fileInput(ARG_DB_BULK_FILE, HtmlUtils.SIZE_60)); bulkSB.append(HtmlUtils.p()); bulkSB.append(msgLabel("Enter names for the numbers")); bulkSB.append(HtmlUtils.br()); bulkSB.append(HtmlUtils.textArea(ARG_DB_NAMES, "#number=name\n#e.g.:\n#303-555-1212= some name\n", 8, 50)); bulkSB.append(HtmlUtils.p()); bulkSB.append(HtmlUtils.formEntry("", HtmlUtils.checkbox(ARG_ANONYMIZE, "true", false) + " " + "Anonymize numbers")); bulkSB.append(HtmlUtils.p()); bulkSB.append(bulkButtons); bulkSB.append(HtmlUtils.formClose()); Utils.append(sb, bulkSB.toString()); } /** * _more_ * * @param date _more_ * * @return _more_ */ public String formatDate(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); return sdf.format(date); } /** * _more_ * * @param args _more_ * * @throws Exception _more_ */ public static void main(String[] args) throws Exception { /* Hashtable<String,CellSite> sites = CellSite.getSites(CellSite.CARRIER_VERIZON); for(String callFile: args) { String delimiter = "\r"; String contents = IOUtil.readContents(callFile, CellSite.class); } */ } /** * Class description * * * @version $version$, Fri, Aug 23, '13 * @author Enter your name here... */ public static class Number implements Comparable { /** _more_ */ String number; /** _more_ */ String name; /** _more_ */ int count = 0; /** _more_ */ Hashtable<Number, List<Object[]>> outboundCalls = new Hashtable<Number, List<Object[]>>(); /** _more_ */ Hashtable<Number, List<Object[]>> inboundCalls = new Hashtable<Number, List<Object[]>>(); /** _more_ */ List<Number> outbound = new ArrayList<Number>(); /** _more_ */ List<Number> inbound = new ArrayList<Number>(); /** * _more_ * * @param number _more_ * @param name _more_ */ public Number(String number, String name) { this.number = number; this.name = name; } /** * _more_ * * @param n _more_ * @param tuple _more_ */ public void addOutbound(Number n, Object[] tuple) { count++; List<Object[]> calls = outboundCalls.get(n); if (calls == null) { outbound.add(n); outboundCalls.put(n, calls = new ArrayList<Object[]>()); } calls.add(tuple); } /** * _more_ * * @param n _more_ * @param tuple _more_ */ public void addInbound(Number n, Object[] tuple) { count++; List<Object[]> calls = inboundCalls.get(n); if (calls == null) { inbound.add(n); inboundCalls.put(n, calls = new ArrayList<Object[]>()); } calls.add(tuple); } /** * _more_ * * @param n _more_ * * @return _more_ */ public List<Object[]> getOutboundCalls(Number n) { return outboundCalls.get(n); } /** * _more_ * * @param n _more_ * * @return _more_ */ public List<Object[]> getInboundCalls(Number n) { return inboundCalls.get(n); } /** * _more_ * * @param n _more_ * * @return _more_ */ public int getOutboundCount(Number n) { return outboundCalls.get(n).size(); } /** * _more_ * * @param n _more_ * * @return _more_ */ public int getInboundCount(Number n) { return inboundCalls.get(n).size(); } /** * _more_ * * @return _more_ */ public List<Number> getSortedOutbound() { Comparator comp = new Comparator() { public int compare(Object o1, Object o2) { Number e1 = (Number) o1; Number e2 = (Number) o2; int c1 = getOutboundCount(e1); int c2 = getOutboundCount(e2); if (c1 < c2) { return 1; } if (c1 > c2) { return -1; } return 0; } }; Object[] array = outbound.toArray(); Arrays.sort(array, comp); return (List<Number>) Misc.toList(array); } /** * _more_ * * @return _more_ */ public List<Number> getSortedInbound() { Comparator comp = new Comparator() { public int compare(Object o1, Object o2) { Number e1 = (Number) o1; Number e2 = (Number) o2; int c1 = getInboundCount(e1); int c2 = getInboundCount(e2); if (c1 < c2) { return 1; } if (c1 > c2) { return -1; } return 0; } }; Object[] array = inbound.toArray(); Arrays.sort(array, comp); return (List<Number>) Misc.toList(array); } /** * _more_ * * @param o _more_ * * @return _more_ */ public int compareTo(Object o) { Number that = (Number) o; if (this.count < that.count) { return 1; } if (this.count > that.count) { return -1; } return 0; } /** * _more_ * * @return _more_ */ @Override public int hashCode() { return number.hashCode(); } /** * _more_ * * @param o _more_ * * @return _more_ */ @Override public boolean equals(Object o) { if (!(o instanceof Number)) { return false; } return number.equals(((Number) o).number); } } }