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
021/**
022 * allows for easy visualization of channel utilization. 
023 * It shows messages coming through in an
024 * 'Oscilloscope' style clickeable window.
025 * @see ISOMeter
026 * @see ISOMsgPanel
027 * @serial
028 */
029
030import org.jpos.iso.*;
031
032import javax.swing.*;
033import java.awt.*;
034import java.util.Observable;
035import java.util.Observer;
036
037public class ISOChannelPanel extends JPanel implements Observer {
038    private static final long serialVersionUID = -8069489863639386589L;
039    /**
040     * @serial
041     */
042    ISOMeter meter;
043    /**
044     * @serial
045     */
046    DefaultListModel log;
047    /**
048     * @serial
049     */
050    String symbolicName;
051
052    private int[] protectFields = null;
053    private int[] wipeFields    = null;
054
055    public static final int LOG_CAPACITY = 250;
056
057    public ISOChannelPanel (ISOChannel channel, String symbolicName)
058    {
059        super();
060        this.symbolicName = symbolicName;
061        setLayout(new FlowLayout());
062        setBorder(BorderFactory.createRaisedBevelBorder());
063        log = new DefaultListModel();
064        add(createCountersPanel());
065        meter.setConnected(channel.isConnected());
066        if (channel instanceof Observable) 
067            ((Observable)channel).addObserver(this);
068    }
069    /**
070     * Unconnected constructor allows for instantiation of
071     * ISOChannelPanel without associated ISOChannel
072     * (that can be attached later)
073     */
074    public ISOChannelPanel (String symbolicName) {
075        super();
076        this.symbolicName = symbolicName;
077        setLayout(new FlowLayout());
078        setBorder(BorderFactory.createRaisedBevelBorder());
079        log = new DefaultListModel();
080        add(createCountersPanel());
081        meter.setConnected(false);
082    }
083
084    public final String getSymbolicName() {
085        return symbolicName;
086    }
087    public final ListModel getLog() {
088        return log;
089    }
090
091    public void update(Observable o, Object arg) {
092        if (arg != null && arg instanceof ISOMsg) {
093            ISOMsg m = (ISOMsg) arg;
094            try {
095                String mti = (String) m.getValue(0);
096                int imti   = Integer.parseInt(mti);
097                if (m.isIncoming())
098                    meter.setValue(-imti, mti);
099                else 
100                    meter.setValue(imti, mti);
101
102                // log.insertElementAt(m,0);
103                log.addElement(getProtectedClone (m));
104                if (log.getSize() > LOG_CAPACITY) 
105                    log.remove(0);
106
107            } catch (ISOException e) { 
108                meter.setValue(ISOMeter.mass, "ERROR");
109            }
110            meter.setValue(ISOMeter.mass);
111        }
112        if (o instanceof BaseChannel) {
113            BaseChannel c = (BaseChannel) o;
114            meter.setConnected(c.isConnected());
115            int cnt[] = c.getCounters();
116            try {
117                meter.setPositiveCounter(
118                    ISOUtil.zeropad(Integer.toString(cnt[ISOChannel.TX % 1000000000]), 9)
119                );
120                meter.setNegativeCounter(
121                    ISOUtil.zeropad(Integer.toString(cnt[ISOChannel.RX] % 1000000000), 9)
122                );
123            } catch (ISOException e) { }
124        } else if (o instanceof ISOServer) {
125            final ISOServer server = (ISOServer) o;
126            final Runnable updateIt = new Runnable() {
127                public void run() {
128                    ISOUtil.sleep (250L);
129                    int active = server.getActiveConnections();
130                    meter.setConnected(active > 0);
131                    try {
132                        meter.setPositiveCounter(
133                            ISOUtil.zeropad(Integer.toString(active), 6)
134                        );
135                    } catch (ISOException e) { }
136                    meter.repaint();
137                }
138            };
139            SwingUtilities.invokeLater (updateIt);
140        } else 
141            meter.setConnected(true);
142    }
143    public ISOMeter getISOMeter() {
144        return meter;
145    }
146    public void setProtectFields (int[] fields) {
147        protectFields = fields;
148    }
149    public void setWipeFields (int[] fields) {
150        wipeFields    = fields;
151    }
152    private JPanel createCountersPanel() {
153        JPanel A = new JPanel() {
154
155            private static final long serialVersionUID = 1175437215105556679L;
156
157            public Insets getInsets() {
158                return new Insets(10,10,10,10);
159            }
160        };
161
162        A.setLayout(new BorderLayout());
163
164        meter = new ISOMeter(this);
165
166        JLabel l = new JLabel(symbolicName);
167        A.add(l, BorderLayout.NORTH);
168        A.add(meter, BorderLayout.CENTER);
169        // meter.start(); -- ISOMeter has auto-start now
170        return A;
171    }
172    private ISOMsg getProtectedClone (ISOMsg m) throws ISOException {
173        ISOMsg pm = (ISOMsg) m.clone ();
174        if (protectFields != null)
175            checkProtected(pm);
176        if (wipeFields != null)
177            checkHidden (pm);
178        return pm;
179    }
180    private void checkProtected (ISOMsg m) throws ISOException {
181        for (int f : protectFields) {
182            if (m.hasField(f))
183                m.set(f, ISOUtil.protect(m.getString(f)));
184        }
185    }
186    private void checkHidden (ISOMsg m) throws ISOException {
187        for (int f : wipeFields) {
188            if (m.hasField(f))
189                m.set(f, "[WIPED]");
190        }
191    }
192}
193