Wednesday, December 15, 2010

How to implement a 'repeating' Swing JButton ?

Sometimes you want to repeat your JButton action after the button was pressed. This is definitely not rocket-science, but I thought it's nice and small enough to share. Here's the usual code with a one-click action: a 'Next' button that selects the next row in a table.

    nextButton.addActionListener( new ActionListener() {
      public void actionPerformed(ActionEvent arg0)
      {
        selectNextRow(...);
      }});
For a repeating button, you can replace this code with the code snippet below. Adjust the times appropriately. I wonder why this isn't standard functionality in a Swing JButton(..., startMsec, repeatMsec) ?

    nextButton.addMouseListener( new MouseAdapter() {
      
      Timer repeatTimer;
      
      public void mousePressed(MouseEvent arg0)
      {
        selectNextRow(...); // initial execution
        
        repeatTimer = new Timer(100, new ActionListener() {
          public void actionPerformed(ActionEvent e)
          {
            selectNextRow(...); // execute every 100 msec
          }});
        repeatTimer.setInitialDelay(1000); // start repeating only after 1 second
        repeatTimer.start();
      }
      
      public void mouseReleased(MouseEvent arg0)
      {
        repeatTimer.stop();
      }});

Tuesday, May 18, 2010

Managing Oracle Tablespace (ORA-01653 error)

This procedure helped me a bit to manage an Oracle DB's tablespace. I was getting ORA-01653: unable to extend table SYSTEM... errors.
Maybe the following procedure is useful for others as well:
  1. In order to manage/see the current usage, here's a good script posted by 'bipul' on http://forums.oracle.com/forums/thread.jspa?messageID=3590569
  2. To check which data files are used:

    select name from v$datafile

  3. To increase that setting:
alter database datafile 'C:\ORACLEXE\ORADATA\XE\SYSTEM.DBF' autoextend on next 100m maxsize 2000m;

Wednesday, February 24, 2010

Quants

An interesting documentation about quants, including Emanuel Derman,
starts in Dutch first, but in English later.

Monday, February 15, 2010

Java: Sorted List

Sometimes you might have the need for a Java list, that is sorted with every element insertion. If you use a sorted TreeSet, you are stuck with iterators, no random access for elements. If you use an ArrayList, you could call Collections.sort() after every add, but that's not necessarily efficient. Collection.sort() will have to check the order for every element. If your list is long, this might take time.
But here's the trick: if you know your list was already sorted before your insertion, there's no need to re-sort everything again. You can find the proper insertion point with a quick binary search, and insert the new element at the proper position. VoilĂ , your list is always sorted.
Surprisingly simple to do this in Java:



/** A LinkedList that efficiently sorts itself with every add.
 * 
 * @author apodehl
 *
 */
public class SortedList< T extends Comparable> extends LinkedList
{
  /** Adds this element to the list at the proper sorting position.
   * If the element already exists, don't do anything.
   */
  @Override
  public boolean add(T e)
  {
    if( size()==0 ) {
      
      return super.add(e);
    }
    else {
      
      // find insertion index
      int idx = -Collections.binarySearch(this, e)-1;
      
      if( idx < 0 ) {
        return true; // already added
      }
      
      // add at this position
      super.add(idx, e);
      return true;
    }
  }
}



Java BiMap, BidiMap

After doing some research and trying to find just the right Java Bi-Map, I couldn't find any, so I had to roll my own :-( To my surprise, implementation of a Bi-Maps is not straight-forward, there's not such thing as the 'one Bi-Map functionality'.
The interesting case is this one: say there are mappings A->1 and B->2. What happens once you insert C->2 ?
Will you remove B->2 to ensure uniqueness of keys and values ? (resulting in A->1 and C->2)
or not, resulting in A->1, B->2 and C->2. Please note that in the latter case, there's no well-defined lookup for value "2". Is it B or is it C ?
So what I needed was uniqueness of both keys and values, in all cases, using generics. Here it goes:


import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * One possible implementation of a Bi-directional Map.
 * 
 * Note: there are several variations of BiMap, depending on the behaviour of put(k,v)... Is it allowed to have more
 * than one k for one value ?? Modify
 * 
 * @author apodehl
 * 
 * @param 
 * @param 
 */
public class BiMap implements Map
{
  Map keyVal; // maps key->value

  Map valKey; // maps value->key

  public BiMap()
  {
    keyVal = new LinkedHashMap();
    valKey = new LinkedHashMap();
  }

  @Override
  public V put(K key, V val)
  {
    // --- this implementation allows one-to-one ONLY !! ---
    if (valKey.containsKey(val)) {
      keyVal.remove(valKey.get(val));
    }
    if (keyVal.containsKey(key)) {
      valKey.remove(keyVal.get(key));
    }
    // --- remove above if that's not what you want ---

    // 
    valKey.put(val, key);
    return keyVal.put(key, val);
  }

  @Override
  public void putAll(Map< ? extends K, ? extends V> m)
  {
    for (Entry< ? extends K, ? extends V> e : m.entrySet()) {
      put(e.getKey(), e.getValue());
    }
  }

  /**
   * Type-safe get.
   * 
   * @param key
   * @return
   */
  public K getKey(V val)
  {
    return valKey.get(val);
  }

  /**
   * Type-safe get.
   * 
   * @param key
   * @return
   */
  public V getVal(K key)
  {
    return keyVal.get(key);
  }

  @Override
  // unfortunately Map interface isn't type-safe
  public V get(Object key)
  {
    return getVal((K) key);
  }

  /**
   * Type-safe contains.
   * 
   * @param key
   * @return
   */
  public boolean contains(K key)
  {
    if (keyVal == null) return false;
    return keyVal.containsKey(key);
  }

  /**
   * Type-safe containsValue.
   * 
   * @param key
   * @return
   */
  public boolean containsVal(V val)
  {
    if (valKey == null) return false;
    return valKey.containsKey(val);
  }

  // unfortunately Map interface isn't type safe here ..
  @Override
  public boolean containsKey(Object key)
  {
    return contains((K) key);
  }

  // unfortunately Map interface isn't type safe here ..
  @Override
  public boolean containsValue(Object value)
  {
    return containsVal((V) value);
  }

  @Override
  public Set< java.util.Map.Entry> entrySet()
  {
    return keyVal.entrySet();
  }

  @Override
  public boolean isEmpty()
  {
    return keyVal.isEmpty();
  }

  @Override
  public int size()
  {
    return keyVal.size();
  }

  @Override
  public Collection values()
  {
    return keyVal.values();
  }

  public V removeByKey(K key)
  {
    V val = keyVal.remove(key);
    valKey.remove(val);
    return val;
  }

  public K removeByVal(V val)
  {
    K key = valKey.remove(val);
    keyVal.remove(key);
    return key;
  }

  // unfortunately Map interface isn't type-safe
  @Override
  public V remove(Object key)
  {
    return removeByKey((K) key);
  }

  @Override
  public Set keySet()
  {
    return keyVal.keySet();
  }

  @Override
  public void clear()
  {
    keyVal.clear();
    valKey.clear();
  }

  public String toString()
  {
    String s = "BiMap:\n";
    s += "  key->value: " + keyVal.toString();
    s += "\n";
    s += "  value->key: " + valKey.toString();
    return s;
  }

  public static void main(String[] args)
  {

    BiMap biMap = new BiMap();
    biMap.put("A", 1);
    biMap.put("B", 2);
    System.out.println(biMap); // {A=1, B=2}

    biMap.put("C", 2);
    System.out.println(biMap); // {A=1, C=2}

    biMap.removeByVal(1);
    System.out.println(biMap); // {C=2}
  }
}

Wednesday, December 23, 2009

Redundant home internet with a Surf Sticks and Internet Connection Sharing

If you have a not-so-reliable ISP and an UMTS surf stick you can configure your home internet to be more redundant by setting up the surf stick as secondary gateway and DNS server for all your machines on a local network.
Takes a while to set up, but its worth it :-)
Assumption: you already have a primary internet gateway (e.g. DSL/Cable) on 192.168.0.1.
Internet host setup (sometimes connected directly through a surf stick):
  1. Setup your dial-up connection to use 'Internet Connection Sharing' (ICS) as described, for example here: http://support.microsoft.com/kb/306126
  2. Make sure that for Internet Connection Sharing 'Settings' you have enabled DNS to be provided by this new Internet host. Possibly DHCP, but not for now.
  3. Also make sure that the LAN network interface (on a laptop, that's usually 'Local Area Connection') now uses a static IP. Set it the way you would like your new internet gateway to appear on your home network. For example in my case, I already have a default gateway on192.168.0.1, so the new Internet-Host, should still use this primary gateway while it is not connected through the surf stick. The new internet host's ip is 192.168.0.100
Ethernet adapter Local Area Connection:
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Intel(R) 82567LM Gigabit Network Connection
Dhcp Enabled. . . . . . . . . . . : No
IP Address. . . . . . . . . . . . : 192.168.0.100
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.0.1
DNS Servers . . . . . . . . . . . : 192.168.0.1
So the Internet Host (my laptop with a surf stick) will use IP and DNS from 192.168.0.1 if it currently isn't connected directly.
Client Machine Setup:
The client machines on the network 192.168.0.x must be configured to use both, the primary gateway at 192.168.0.1 and, if not available, the secondary gateway at 192.168.0.100.
On each client machine, go to 'Local Area Connection' -> Properties -> TCP/IP ->Properties and specify an "Alternate DNS Server" of 192.168.0.100 and click 'Advanced' to add a new Default Gateway. Click 'Add' and set the 'TCP/IP Gateway Address' to 192.168.0.100.
Now each client uses 192.168.0.1, while your DSL/Cable internet is available, and 192.168.0.100 otherwise.
The whole configuration with DHCP is similar, you just need to prepolute the DHCP answers with about the same settings (Default gateways and DNS: 192.168.0.1 and 192.168.0.100) .

Friday, October 30, 2009

MAC/IP lookup

I was trying to figure out more about a MAC address and found an interesting lookup mechanism:
To be concise, all lookups on one page: