001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.iso.gui; 020 021import org.jpos.iso.ISOException; 022import org.jpos.iso.ISOMsg; 023import org.jpos.iso.ISOPackager; 024import org.jpos.iso.ISOUtil; 025 026import javax.swing.*; 027import javax.swing.event.ListSelectionEvent; 028import javax.swing.event.ListSelectionListener; 029import javax.swing.table.AbstractTableModel; 030import javax.swing.table.TableModel; 031import java.awt.*; 032import java.util.Vector; 033 034/** 035 * Called from ISOChannelPanel when you click on it's ISOMeter. 036 * It enable field and header visualization by means of visual 037 * components such as JTable 038 * 039 * @see ISOChannelPanel 040 * @see ISORequestListenerPanel 041 */ 042@SuppressWarnings({"unchecked", "deprecation"}) 043public class ISOMsgPanel extends JPanel { 044 045 private static final long serialVersionUID = 7779880613544725704L; 046 /** 047 * Message currently displayed by the panel. 048 * 049 * @serial serialized message snapshot 050 */ 051 ISOMsg m; 052 /** 053 * Ordered collection of populated field numbers. 054 * 055 * @serial field-number list used by the table model 056 */ 057 Vector validFields; 058 /** Constructs a panel for the given message. 059 * @param m the ISO message to display 060 * @param withDump if true, include a hex dump 061 */ 062 public ISOMsgPanel(ISOMsg m, boolean withDump) { 063 super(); 064 this.m = m; 065 setLayout(new BorderLayout()); 066 setBorder(BorderFactory.createRaisedBevelBorder()); 067 setValidFields(); 068 add(createISOMsgTable(), BorderLayout.CENTER); 069 if (withDump) 070 add(createISOMsgDumpPanel(), BorderLayout.SOUTH); 071 } 072 /** Constructs a panel for the given message. 073 * @param m the ISO message to display 074 */ 075 public ISOMsgPanel(ISOMsg m) { 076 this(m, false); 077 } 078 private void setValidFields() { 079 validFields = new Vector(); 080 for (int i=0; i<=m.getMaxField(); i++) 081 if (m.hasField(i)) 082 validFields.addElement(i); 083 } 084 private JComponent createISOMsgTable() { 085 TableModel dataModel = new AbstractTableModel() { 086 087 private static final long serialVersionUID = 8917029825751856951L; 088 089 @Override 090 public int getColumnCount() { 091 return 3; 092 } 093 094 @Override 095 public int getRowCount() { 096 return validFields.size(); 097 } 098 099 @Override 100 public String getColumnName(int columnIndex) { 101 switch (columnIndex) { 102 case 0 : 103 return "#"; 104 case 1 : 105 return "Content"; 106 case 2 : 107 return "Description"; 108 default: 109 return ""; 110 } 111 } 112 113 @Override 114 public Object getValueAt(int row, int col) { 115 switch (col) { 116 case 0 : 117 return validFields.elementAt(row); 118 case 1 : 119 int index = (Integer) validFields.elementAt(row); 120 121 Object obj = m.getValue(index); 122 if (obj instanceof String) { 123 String s = obj.toString(); 124 switch (index) { 125 case 2 : 126 case 35: 127 case 45: 128 s = ISOUtil.protect(s); 129 break; 130 case 14: 131 s = "----"; 132 } 133 return s; 134 } 135 else if (obj instanceof byte[]) 136 return ISOUtil.hexString((byte[]) obj); 137 else if (obj instanceof ISOMsg) 138 return "<ISOMsg>"; 139 break; 140 case 2 : 141 int i = (Integer) validFields.elementAt(row); 142 ISOPackager p = m.getPackager(); 143 return p.getFieldDescription(m,i); 144 } 145 return "<???>"; 146 } 147 }; 148 JTable table = new JTable(dataModel); 149 table.getColumnModel().getColumn(0).setPreferredWidth(10); 150 table.setPreferredScrollableViewportSize( 151 new Dimension (500,table.getRowCount()*table.getRowHeight())); 152 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 153 154 ListSelectionModel rowSM = table.getSelectionModel(); 155 rowSM.addListSelectionListener(new ListSelectionListener() { 156 public void valueChanged(ListSelectionEvent e) { 157 if (e.getValueIsAdjusting()) 158 return; 159 160 ListSelectionModel lsm = 161 (ListSelectionModel)e.getSource(); 162 if (!lsm.isSelectionEmpty()) { 163 int selectedRow = lsm.getMinSelectionIndex(); 164 int index = (Integer) 165 validFields.elementAt(selectedRow); 166 167 Object obj = m.getValue(index); 168 if (obj instanceof ISOMsg) { 169 ISOMsg sm = (ISOMsg) obj; 170 JFrame f = new JFrame("ISOMsg field "+index); 171 ISOMsgPanel p = new ISOMsgPanel(sm, false); 172 f.getContentPane().add(p); 173 f.pack(); 174 f.show(); 175 } 176 } 177 } 178 }); 179 180 return new JScrollPane(table); 181 } 182 JComponent createISOMsgDumpPanel() { 183 JPanel p = new JPanel(); 184 JTextArea t = new JTextArea(3,20); 185 186 p.setLayout(new BorderLayout()); 187 p.setBackground(Color.white); 188 p.setBorder(BorderFactory.createLoweredBevelBorder()); 189 p.add(new JLabel("Dump", SwingConstants.LEFT), 190 BorderLayout.NORTH); 191 t.setFont(new Font ("Helvetica", Font.PLAIN, 8)); 192 t.setLineWrap(true); 193 try { 194 StringBuilder buf = new StringBuilder(); 195 if (m.getHeader() != null) { 196 buf.append("--[Header]--\n"); 197 buf.append(ISOUtil.hexString(m.getHeader())); 198 buf.append("\n--[Msg]--\n"); 199 } 200 byte[] b = m.pack(); 201 buf.append (ISOUtil.hexString(b)); 202 t.setText(buf.toString()); 203 } catch (ISOException e) { 204 t.setText(e.toString()); 205 t.setForeground(Color.red); 206 } 207 p.add(t, BorderLayout.CENTER); 208 return p; 209 } 210}