Full Code of sf105/goos-code for AI

master 5dff69366dad cached
64 files
72.2 KB
19.5k tokens
265 symbols
1 requests
Download .txt
Repository: sf105/goos-code
Branch: master
Commit: 5dff69366dad
Files: 64
Total size: 72.2 KB

Directory structure:
gitextract_xhlrihb_/

├── .classpath
├── .project
├── build.xml
├── lib/
│   ├── deploy/
│   │   ├── commons-io-1.4.jar
│   │   ├── commons-lang-2.4.jar
│   │   ├── smack_3_1_0.jar
│   │   └── smackx_3_1_0.jar
│   └── develop/
│       ├── cglib-nodep-2.2.jar
│       ├── commons-io-1.4-sources.jar
│       ├── commons-lang-2.4-sources.jar
│       ├── hamcrest-core-1.2.jar
│       ├── hamcrest-core-SNAPSHOT.jar
│       ├── hamcrest-library-1.2.jar
│       ├── hamcrest-library-SNAPSHOT.jar
│       ├── jmock-2.6-SNAPSHOT.jar
│       ├── jmock-junit4-2.6-SNAPSHOT.jar
│       ├── jmock-legacy-2.6-SNAPSHOT.jar
│       ├── junit-4.6-src.jar
│       ├── junit-dep-4.6.jar
│       ├── objenesis-1.0.jar
│       ├── windowlicker-core-DEV.jar
│       └── windowlicker-swing-DEV.jar
├── license.txt
├── src/
│   └── auctionsniper/
│       ├── Auction.java
│       ├── AuctionEventListener.java
│       ├── AuctionHouse.java
│       ├── AuctionSniper.java
│       ├── Main.java
│       ├── SniperCollector.java
│       ├── SniperLauncher.java
│       ├── SniperListener.java
│       ├── SniperPortfolio.java
│       ├── SniperSnapshot.java
│       ├── SniperState.java
│       ├── UserRequestListener.java
│       ├── ui/
│       │   ├── Column.java
│       │   ├── MainWindow.java
│       │   ├── SnipersTableModel.java
│       │   └── SwingThreadSniperListener.java
│       ├── util/
│       │   ├── Announcer.java
│       │   └── Defect.java
│       └── xmpp/
│           ├── AuctionMessageTranslator.java
│           ├── LoggingXMPPFailureReporter.java
│           ├── XMPPAuction.java
│           ├── XMPPAuctionException.java
│           ├── XMPPAuctionHouse.java
│           └── XMPPFailureReporter.java
├── test/
│   ├── end-to-end/
│   │   └── test/
│   │       └── endtoend/
│   │           └── auctionsniper/
│   │               ├── ApplicationRunner.java
│   │               ├── AuctionLogDriver.java
│   │               ├── AuctionSniperDriver.java
│   │               ├── AuctionSniperEndToEndTest.java
│   │               └── FakeAuctionServer.java
│   ├── integration/
│   │   └── test/
│   │       └── integration/
│   │           └── auctionsniper/
│   │               ├── ui/
│   │               │   └── MainWindowTest.java
│   │               └── xmpp/
│   │                   └── XMPPAuctionHouseTest.java
│   └── unit/
│       └── test/
│           └── auctionsniper/
│               ├── AuctionSniperTest.java
│               ├── SniperLauncherTest.java
│               ├── SniperPortfolioTest.java
│               ├── SniperSnapshotTest.java
│               ├── SniperStateTests.java
│               ├── ui/
│               │   ├── ColumnTest.java
│               │   └── SnipersTableModelTest.java
│               └── xmpp/
│                   ├── AuctionMessageTranslatorTest.java
│                   └── LoggingXMPPFailureReporterTest.java
└── tools/
    └── openfire-version-is-3.6.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .classpath
================================================
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" path="src"/>
	<classpathentry kind="src" path="test/end-to-end"/>
	<classpathentry kind="src" path="test/unit"/>
	<classpathentry kind="src" path="test/integration"/>
	<classpathentry kind="lib" path="lib/deploy/commons-io-1.4.jar" sourcepath="lib/develop/commons-io-1.4-sources.jar"/>
	<classpathentry kind="lib" path="lib/deploy/commons-lang-2.4.jar"/>
	<classpathentry kind="lib" path="lib/deploy/smack_3_1_0.jar"/>
	<classpathentry kind="lib" path="lib/deploy/smackx_3_1_0.jar"/>
	<classpathentry kind="lib" path="lib/develop/cglib-nodep-2.2.jar"/>
	<classpathentry kind="lib" path="lib/develop/junit-4.6-src.jar"/>
	<classpathentry kind="lib" path="lib/develop/junit-dep-4.6.jar"/>
	<classpathentry kind="lib" path="lib/develop/objenesis-1.0.jar"/>
	<classpathentry kind="lib" path="lib/develop/windowlicker-core-DEV.jar" sourcepath="/windowlicker/src/swing/main"/>
	<classpathentry kind="lib" path="lib/develop/windowlicker-swing-DEV.jar" sourcepath="/windowlicker/src/swing/main"/>
	<classpathentry kind="lib" path="lib/develop/jmock-legacy-2.6-SNAPSHOT.jar"/>
	<classpathentry kind="lib" path="lib/develop/jmock-2.6-SNAPSHOT.jar"/>
	<classpathentry kind="lib" path="lib/develop/jmock-junit4-2.6-SNAPSHOT.jar"/>
	<classpathentry kind="lib" path="lib/develop/hamcrest-core-SNAPSHOT.jar"/>
	<classpathentry kind="lib" path="lib/develop/hamcrest-library-SNAPSHOT.jar"/>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
	<classpathentry kind="output" path="bin"/>
</classpath>


================================================
FILE: .project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>auction-example-06</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>org.eclipse.jdt.core.javabuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>org.eclipse.jdt.core.javanature</nature>
	</natures>
</projectDescription>


================================================
FILE: build.xml
================================================
<project name="Auction Sniper" default="build">
    <property name="build.dir" location="build" />
    <property name="src.dir" location="src" />
    <property name="test.dir" location="test"/>
    <property name="lib.dir" value="lib" />
    <property name="app.classes.dir" location="${build.dir}/classes/app" />
    <property name="test.classes.dir" location="${build.dir}/classes/test" />
    
    <path id="app.lib.path">
        <fileset dir="${lib.dir}/deploy" includes="*.jar"/>
    </path>

    <path id="test.lib.path">
        <fileset dir="${lib.dir}/develop" includes="*.jar" excludes="*-src.jar"/>
        <path location="${app.classes.dir}" />
        <path refid="app.lib.path"/>
    </path>

    <target name="clean">
    	<delete dir="${build.dir}" quiet="true" />
    </target>
    
    <target name="app.compile">
        <property name="app.src.dir" location="${src.dir}" />
    	<mkdir dir="${app.classes.dir}" />
        <javac destdir="${app.classes.dir}"
               srcdir="${app.src.dir}"
               classpathref="app.lib.path" 
        	   debug="on"/>
    </target>

    <target name="test.compile"
        	depends="app.compile">
        <property name="test.src.dir" location="${test.dir}/end-to-end" />
    	<mkdir dir="${test.classes.dir}" />
        <javac destdir="${test.classes.dir}"
               srcdir="${test.src.dir}"
               classpathref="test.lib.path"
               debug="on"/>
    </target>
    
    <target name="openfire.check">
        <waitfor checkevery="1" checkeveryunit="second" maxwait="20" timeoutproperty="openfire.is.down">
            <http url="http://localhost:9090" />
        </waitfor>
    </target>
    
    <target name="test.run"
    		description="Run the tests" 
    		depends="test.compile, openfire.check" >
        <fail message="OpenFire is not running" if="openfire.is.down"/>
        <property name="test.reports.dir" location="${build.dir}/testreports"/>
        <mkdir dir="${test.reports.dir}"/>
        <junit>
            <batchtest todir="${test.reports.dir}" haltonfailure="true" haltonerror="true">
                <formatter type="plain"/>
                <fileset dir="${test.dir}/end-to-end" includes="**/*Test.java" />
            </batchtest>
            <classpath>
                <path refid="test.lib.path" />
                <path location="${test.classes.dir}" />
            </classpath>
        </junit>
    </target>
    
    <target name="build"
    	description="Clean, build, and full test" 
   		depends="clean, test.run" />
</project>

================================================
FILE: license.txt
================================================
This project is Copyright 2009 Stephen Freeman and Nathaniel Pryce

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: src/auctionsniper/Auction.java
================================================
package auctionsniper;

public interface Auction {

  void join();
  void bid(int amount);
  void addAuctionEventListener(AuctionEventListener listener);
}


================================================
FILE: src/auctionsniper/AuctionEventListener.java
================================================
package auctionsniper;

import java.util.EventListener;

public interface AuctionEventListener extends EventListener {
  enum PriceSource {
    FromSniper, FromOtherBidder;
  };
  
  void auctionClosed();
  void currentPrice(int price, int increment, PriceSource priceSource);
  void auctionFailed();
}


================================================
FILE: src/auctionsniper/AuctionHouse.java
================================================
package auctionsniper;

import auctionsniper.UserRequestListener.Item;

public interface AuctionHouse {
  Auction auctionFor(Item item); 
}


================================================
FILE: src/auctionsniper/AuctionSniper.java
================================================
package auctionsniper;

import auctionsniper.UserRequestListener.Item;
import auctionsniper.util.Announcer;

public class AuctionSniper implements AuctionEventListener {
  private final Announcer<SniperListener> listeners = Announcer.to(SniperListener.class);
  private final Auction auction;
  private SniperSnapshot snapshot;
  private final Item item; 
    
  public AuctionSniper(Item item, Auction auction) {
    this.item = item;
    this.auction = auction;
    this.snapshot = SniperSnapshot.joining(item.identifier);
  }

  public void addSniperListener(SniperListener listener) {
    listeners.addListener(listener);
  }
  
  public void auctionClosed() {
    snapshot = snapshot.closed();
    notifyChange();
  }

  public void auctionFailed() {
    snapshot = snapshot.failed(); 
    notifyChange();
  }
  
  public void currentPrice(int price, int increment, PriceSource priceSource) {
    switch(priceSource) {
    case FromSniper:
      snapshot = snapshot.winning(price); 
      break;
    case FromOtherBidder:
      int bid = price + increment;
      if (item.allowsBid(bid)) {
        auction.bid(bid);
        snapshot = snapshot.bidding(price, bid);
      } else {
        snapshot = snapshot.losing(price);
      }
      break;
    }
    notifyChange();
  }

  public SniperSnapshot getSnapshot() {
    return snapshot;
  }
  
  private void notifyChange() {
    listeners.announce().sniperStateChanged(snapshot);
  }

}


================================================
FILE: src/auctionsniper/Main.java
================================================
package auctionsniper;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.SwingUtilities;

import auctionsniper.ui.MainWindow;
import auctionsniper.xmpp.XMPPAuctionHouse;

public class Main {
  private static final int ARG_HOSTNAME = 0;
  private static final int ARG_USERNAME = 1;
  private static final int ARG_PASSWORD = 2;

  private final SniperPortfolio portfolio = new SniperPortfolio(); 

  private MainWindow ui;

  public Main() throws Exception {
    startUserInterface();
  }

  public static void main(String... args) throws Exception {
    Main main = new Main();
    XMPPAuctionHouse auctionHouse = XMPPAuctionHouse.connect(args[ARG_HOSTNAME], args[ARG_USERNAME], args[ARG_PASSWORD]); 
    main.disconnectWhenUICloses(auctionHouse);
    main.addUserRequestListenerFor(auctionHouse);
  }

  private void startUserInterface() throws Exception {
    SwingUtilities.invokeAndWait(new Runnable() {
      public void run() {
        ui = new MainWindow(portfolio);
      }
    });
  }

  private void disconnectWhenUICloses(final XMPPAuctionHouse auctionHouse) { 
    ui.addWindowListener(new WindowAdapter() { 
      @Override public void windowClosed(WindowEvent e) { 
        auctionHouse.disconnect(); 
      } 
    }); 
  } 

  private void addUserRequestListenerFor(final AuctionHouse auctionHouse) {
    ui.addUserRequestListener(new SniperLauncher(auctionHouse, portfolio)); 

  } 
}


================================================
FILE: src/auctionsniper/SniperCollector.java
================================================
package auctionsniper;

public interface SniperCollector {
  void addSniper(AuctionSniper sniper);
}


================================================
FILE: src/auctionsniper/SniperLauncher.java
================================================
package auctionsniper;


public class SniperLauncher implements UserRequestListener {
  private final AuctionHouse auctionHouse;
  private final SniperCollector collector;

  public SniperLauncher(AuctionHouse auctionHouse, SniperCollector collector) {
    this.auctionHouse = auctionHouse;
    this.collector = collector;
  }

  public void joinAuction(Item item) { 
    Auction auction = auctionHouse.auctionFor(item);
    AuctionSniper sniper = new AuctionSniper(item, auction); 
    auction.addAuctionEventListener(sniper); 
    collector.addSniper(sniper); 
    auction.join(); 
  }
}

================================================
FILE: src/auctionsniper/SniperListener.java
================================================
package auctionsniper;

import java.util.EventListener;

public interface SniperListener extends EventListener { 
  void sniperStateChanged(SniperSnapshot snapshot);
}

================================================
FILE: src/auctionsniper/SniperPortfolio.java
================================================
package auctionsniper;

import java.util.ArrayList;
import java.util.EventListener;

import auctionsniper.util.Announcer;

public class SniperPortfolio implements SniperCollector {
  public interface PortfolioListener extends EventListener {
    void sniperAdded(AuctionSniper sniper);
  }
 
  private final Announcer<PortfolioListener> announcer = Announcer.to(PortfolioListener.class);
  private final ArrayList<AuctionSniper> snipers = new ArrayList<AuctionSniper>();
  
  public void addSniper(AuctionSniper sniper) {
    snipers.add(sniper);
    announcer.announce().sniperAdded(sniper);
  }

  public void addPortfolioListener(PortfolioListener listener) {
    announcer.addListener(listener);
  }
}


================================================
FILE: src/auctionsniper/SniperSnapshot.java
================================================
package auctionsniper;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public class SniperSnapshot {
  public final String itemId;
  public final int lastPrice;
  public final int lastBid;
  public final SniperState state;
  
  public SniperSnapshot(String itemId, int lastPrice, int lastBid, SniperState state) {
    this.itemId = itemId;
    this.lastPrice = lastPrice;
    this.lastBid = lastBid;
    this.state = state;
  }
  
  @Override
  public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj);
  }
  @Override
  public int hashCode() {
    return HashCodeBuilder.reflectionHashCode(this);
  }
  @Override
  public String toString() {
    return ToStringBuilder.reflectionToString(this);
  }

  public static SniperSnapshot joining(String itemId) {
    return new SniperSnapshot(itemId, 0, 0, SniperState.JOINING);
  }

  public SniperSnapshot bidding(int newLastPrice, int newLastBid) {
    return new SniperSnapshot(itemId, newLastPrice, newLastBid, SniperState.BIDDING);
  }

  public SniperSnapshot winning(int newLastPrice) {
    return new SniperSnapshot(itemId, newLastPrice, lastBid, SniperState.WINNING);
  }

  public SniperSnapshot losing(int newLastPrice) {
    return new SniperSnapshot(itemId, newLastPrice, lastBid, SniperState.LOSING);
  }

  public SniperSnapshot closed() {
    return new SniperSnapshot(itemId, lastPrice, lastBid, state.whenAuctionClosed());
  }

  public SniperSnapshot failed() {
    return new SniperSnapshot(itemId, 0, 0, SniperState.FAILED);
  }

  public boolean isForSameItemAs(SniperSnapshot sniperSnapshot) {
    return itemId.equals(sniperSnapshot.itemId);
  }



}

================================================
FILE: src/auctionsniper/SniperState.java
================================================
package auctionsniper;

import auctionsniper.util.Defect;

public enum SniperState { 
  JOINING {
    @Override public SniperState whenAuctionClosed() { return LOST; } 
  },
  BIDDING { 
    @Override public SniperState whenAuctionClosed() { return LOST; } 
  }, 
  WINNING { 
    @Override public SniperState whenAuctionClosed() { return WON; } 
  }, 
  LOSING {
    @Override public SniperState whenAuctionClosed() { return LOST; } 
  },
  LOST, 
  WON,
  FAILED;

  public SniperState whenAuctionClosed() { 
    throw new Defect("Auction is already closed"); 
  } 
}

================================================
FILE: src/auctionsniper/UserRequestListener.java
================================================
package auctionsniper;

import java.util.EventListener;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

public interface UserRequestListener extends EventListener {
  void joinAuction(Item item);
  
  public static class Item {
    public final String identifier;
    public final int stopPrice;

    public Item(String identifier, int stopPrice) { 
      this.identifier = identifier;
      this.stopPrice = stopPrice; 
    }

    public boolean allowsBid(int bid) {
      return bid <= stopPrice;
    } 

    @Override
    public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); }
    @Override
    public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); }
    @Override
    public String toString() { return "Item: " + identifier + ", stop price: " + stopPrice; }

  }
}


================================================
FILE: src/auctionsniper/ui/Column.java
================================================
package auctionsniper.ui;

import auctionsniper.SniperSnapshot;

public enum Column { 
  ITEM_IDENTIFIER("Item") { 
    @Override public Object valueIn(SniperSnapshot snapshot) { 
      return snapshot.itemId; 
    } 
  }, 
  LAST_PRICE("Last Price") { 
    @Override public Object valueIn(SniperSnapshot snapshot) { 
      return snapshot.lastPrice; 
    } 
  }, 
  LAST_BID("Last Bid") { 
    @Override public Object valueIn(SniperSnapshot snapshot) { 
      return snapshot.lastBid; 
    }    
  }, 
  SNIPER_STATE("State") { 
    @Override public Object valueIn(SniperSnapshot snapshot) { 
      return SnipersTableModel.textFor(snapshot.state); 
    }    
  }; 
  
  abstract public Object valueIn(SniperSnapshot snapshot); 
  
  public final String name;
  
  private Column(String name) { 
    this.name = name; 
  } 

  public static Column at(int offset) { return values()[offset]; } 
}


================================================
FILE: src/auctionsniper/ui/MainWindow.java
================================================
package auctionsniper.ui;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;

import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;

import auctionsniper.UserRequestListener;
import auctionsniper.SniperPortfolio;
import auctionsniper.UserRequestListener.Item;
import auctionsniper.util.Announcer;


public class MainWindow extends JFrame { 
  public static final String APPLICATION_TITLE = "Auction Sniper";
  private static final String SNIPERS_TABLE_NAME = "Snipers Table";
  public static final String MAIN_WINDOW_NAME = "Auction Sniper Main";
  public static final String NEW_ITEM_ID_NAME = "item id";
  public static final String JOIN_BUTTON_NAME = "join button";
  public static final String NEW_ITEM_STOP_PRICE_NAME = "stop price";
  
  private final Announcer<UserRequestListener> userRequests = Announcer.to(UserRequestListener.class); 

  
  public MainWindow(SniperPortfolio portfolio){ 
    super("Auction Sniper"); 
    setName(MainWindow.MAIN_WINDOW_NAME); 
    fillContentPane(makeSnipersTable(portfolio), makeControls());
    pack(); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setVisible(true); 
  } 
  
  public void addUserRequestListener(UserRequestListener userRequestListener) {
    userRequests.addListener(userRequestListener); 
  } 

  private void fillContentPane(JTable snipersTable, JPanel controls) { 
    final Container contentPane = getContentPane(); 
    contentPane.setLayout(new BorderLayout()); 
    contentPane.add(controls, BorderLayout.NORTH); 
    contentPane.add(new JScrollPane(snipersTable), BorderLayout.CENTER); 
  } 
  
  private JPanel makeControls() { 
    final JTextField itemIdField = itemIdField();
    final JFormattedTextField stopPriceField = stopPriceField();

    JPanel controls = new JPanel(new FlowLayout()); 
    controls.add(itemIdField); 
    controls.add(stopPriceField);

    JButton joinAuctionButton = new JButton("Join Auction"); 
    joinAuctionButton.setName(JOIN_BUTTON_NAME); 
    
    joinAuctionButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        userRequests.announce().joinAuction(new Item(itemId(), stopPrice())); 
      } 
      private String itemId() {
        return itemIdField.getText();
      }
      private int stopPrice() { 
        return ((Number)stopPriceField.getValue()).intValue(); 
      } 
    }); 
    controls.add(joinAuctionButton); 
    
    return controls; 
  } 

  private JTextField itemIdField() {
    JTextField itemIdField = new JTextField();
    itemIdField.setColumns(10);
    itemIdField.setName(NEW_ITEM_ID_NAME);
    return itemIdField;
  }

  private JFormattedTextField stopPriceField() {
    JFormattedTextField stopPriceField = new JFormattedTextField(NumberFormat.getIntegerInstance());
    stopPriceField.setColumns(7);
    stopPriceField.setName(NEW_ITEM_STOP_PRICE_NAME);
    return stopPriceField;
  }

  private JTable makeSnipersTable(SniperPortfolio portfolio) { 
    SnipersTableModel model = new SnipersTableModel();
    portfolio.addPortfolioListener(model);
    JTable snipersTable = new JTable(model); 
    snipersTable.setName(SNIPERS_TABLE_NAME); 
    return snipersTable; 
  }

} 


================================================
FILE: src/auctionsniper/ui/SnipersTableModel.java
================================================
package auctionsniper.ui;

import java.util.ArrayList;

import javax.swing.table.AbstractTableModel;

import auctionsniper.AuctionSniper;
import auctionsniper.SniperListener;
import auctionsniper.SniperSnapshot;
import auctionsniper.SniperState;
import auctionsniper.SniperPortfolio.PortfolioListener;
import auctionsniper.util.Defect;

public class SnipersTableModel extends AbstractTableModel implements SniperListener, PortfolioListener {
  private final static String[] STATUS_TEXT = { 
    "Joining", "Bidding", "Winning", "Losing", "Lost", "Won", "Failed" 
  };
  private ArrayList<SniperSnapshot> snapshots = new ArrayList<SniperSnapshot>();

  public int getColumnCount() { 
    return Column.values().length; 
  } 
  
  public int getRowCount() { 
    return snapshots.size();
  }

  @Override public String getColumnName(int column) { 
    return Column.at(column).name; 
  } 

  public Object getValueAt(int rowIndex, int columnIndex) {
    return Column.at(columnIndex).valueIn(snapshots.get(rowIndex)); 
  } 

  public static String textFor(SniperState state) { 
    return STATUS_TEXT[state.ordinal()]; 
  }
  
  public void sniperStateChanged(SniperSnapshot newSnapshot) {
    for (int i = 0; i < snapshots.size(); i++) {
      if (newSnapshot.isForSameItemAs(snapshots.get(i))) {
        snapshots.set(i, newSnapshot); 
        fireTableRowsUpdated(i, i);
        return;
      }
    }
    throw new Defect("No existing Sniper state for " + newSnapshot.itemId);
  }

  public void sniperAdded(AuctionSniper sniper) {
    addSniperSnapshot(sniper.getSnapshot());
    sniper.addSniperListener(new SwingThreadSniperListener(this));
  } 

  private void addSniperSnapshot(SniperSnapshot newSniper) {
    snapshots.add(newSniper);
    int row = snapshots.size() - 1;
    fireTableRowsInserted(row, row);
  }
}


================================================
FILE: src/auctionsniper/ui/SwingThreadSniperListener.java
================================================
/**
 * 
 */
package auctionsniper.ui;

import javax.swing.SwingUtilities;

import auctionsniper.SniperListener;
import auctionsniper.SniperSnapshot;

public class SwingThreadSniperListener implements SniperListener {
  private final SniperListener delegate;
  public SwingThreadSniperListener(SniperListener delegate) {
    this.delegate = delegate;
  }
  public void sniperStateChanged(final SniperSnapshot snapshot) { 
    SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
        delegate.sniperStateChanged(snapshot); 
      } 
    }); 
  }
}

================================================
FILE: src/auctionsniper/util/Announcer.java
================================================
package auctionsniper.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;

public class Announcer<T extends EventListener> {
	private final T proxy;
	private final List<T> listeners = new ArrayList<T>();
	
	
	public Announcer(Class<? extends T> listenerType) {
		proxy = listenerType.cast(Proxy.newProxyInstance(
			listenerType.getClassLoader(), 
			new Class<?>[]{listenerType}, 
			new InvocationHandler() {
				public Object invoke(Object aProxy, Method method, Object[] args) throws Throwable {
					announce(method, args);
					return null;
				}
			}));
	}
	
	public void addListener(T listener) {
		listeners.add(listener);
	}
	
	public void removeListener(T listener) {
		listeners.remove(listener);
	}
	
	public T announce() {
		return proxy;
	}
	
	private void announce(Method m, Object[] args) {
		try {
			for (T listener : listeners) {
				m.invoke(listener, args);
			}
		}
		catch (IllegalAccessException e) {
			throw new IllegalArgumentException("could not invoke listener", e);
		}
		catch (InvocationTargetException e) {
			Throwable cause = e.getCause();
			
			if (cause instanceof RuntimeException) {
				throw (RuntimeException)cause;
			} 
			else if (cause instanceof Error) {
				throw (Error)cause;
			}
			else {
				throw new UnsupportedOperationException("listener threw exception", cause);
			}
		}
	}
	
	public static <T extends EventListener> Announcer<T> to(Class<? extends T> listenerType) {
		return new Announcer<T>(listenerType);
	}
}


================================================
FILE: src/auctionsniper/util/Defect.java
================================================
package auctionsniper.util;

public class Defect extends RuntimeException {

  public Defect() {
    super();
  }

  public Defect(String message, Throwable cause) {
    super(message, cause);
  }

  public Defect(String message) {
    super(message);
  }

  public Defect(Throwable cause) {
    super(cause);
  }

}


================================================
FILE: src/auctionsniper/xmpp/AuctionMessageTranslator.java
================================================
package auctionsniper.xmpp;

import static auctionsniper.AuctionEventListener.PriceSource.FromOtherBidder;
import static auctionsniper.AuctionEventListener.PriceSource.FromSniper;

import java.util.HashMap;
import java.util.Map;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.packet.Message;

import auctionsniper.AuctionEventListener;
import auctionsniper.AuctionEventListener.PriceSource;

public class AuctionMessageTranslator implements MessageListener { 
  private final AuctionEventListener listener;
  private final String sniperId;
  private final XMPPFailureReporter failureReporter;

  public AuctionMessageTranslator(String sniperId, AuctionEventListener listener, XMPPFailureReporter failureReporter) {
    this.sniperId = sniperId;
    this.listener = listener;
    this.failureReporter = failureReporter;
  }

  public void processMessage(Chat chat, Message message) { 
    String messageBody = message.getBody();
    try {
      translate(messageBody);
    } catch (Exception parseException) {
      failureReporter.cannotTranslateMessage(sniperId, messageBody, parseException);
      listener.auctionFailed();
    } 
  }

  private void translate(String messageBody) throws Exception {
    AuctionEvent event = AuctionEvent.from(messageBody);
    
    String eventType = event.type();
    if ("CLOSE".equals(eventType)) { 
      listener.auctionClosed(); 
    } if ("PRICE".equals(eventType)) { 
      listener.currentPrice(event.currentPrice(), event.increment(), 
                            event.isFrom(sniperId)); 
    }
  } 
  
  private static class AuctionEvent {
    private final Map<String, String> fields = new HashMap<String, String>();  
    public String type() throws MissingValueException { return get("Event"); }
    public int currentPrice() throws Exception { return getInt("CurrentPrice"); }
    public int increment() throws Exception { return getInt("Increment"); }
    public PriceSource isFrom(String sniperId) throws MissingValueException {
      return sniperId.equals(bidder()) ? FromSniper : FromOtherBidder;
    }
    
    private String bidder() throws MissingValueException { return get("Bidder"); }
    private int getInt(String fieldName) throws Exception {
      return Integer.parseInt(get(fieldName));
    }
    private String get(String fieldName) throws MissingValueException { 
      final String value = fields.get(fieldName);
      if (value == null) {
        throw new MissingValueException(fieldName);
      }
      return value; 
    }

    private void addField(String field) {
      String[] pair = field.split(":");
      fields.put(pair[0].trim(), pair[1].trim());
    }

    static AuctionEvent from(String messageBody) {
      AuctionEvent event = new AuctionEvent();
      for (String field : fieldsIn(messageBody)) {
        event.addField(field);
      }
      return event;
    }
    
    static String[] fieldsIn(String messageBody) {
      return messageBody.split(";");
    }
  }
  private static class MissingValueException extends Exception {
    public MissingValueException(String fieldName) {
      super("Missing value for " + fieldName);
    }
  }
} 


================================================
FILE: src/auctionsniper/xmpp/LoggingXMPPFailureReporter.java
================================================
package auctionsniper.xmpp;

import java.util.logging.Logger;

public class LoggingXMPPFailureReporter implements XMPPFailureReporter {
  private static final String MESSAGE_FORMAT = "<%s> Could not translate message \"%s\" because \"%s\"";
  private final Logger logger;
  
  public LoggingXMPPFailureReporter(Logger logger) {
    this.logger = logger;
  }

  public void cannotTranslateMessage(String auctionId, String failedMessage, Exception exception) {
    logger.severe(String.format(MESSAGE_FORMAT, auctionId, failedMessage, exception.toString()));
  }
}


================================================
FILE: src/auctionsniper/xmpp/XMPPAuction.java
================================================
package auctionsniper.xmpp;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

import auctionsniper.Auction;
import auctionsniper.AuctionEventListener;
import auctionsniper.util.Announcer;

public class XMPPAuction implements Auction { 
  public static final String JOIN_COMMAND_FORMAT = "SOLVersion: 1.1; Command: JOIN;";
  public static final String BID_COMMAND_FORMAT = "SOLVersion: 1.1; Command: BID; Price: %d;";

  private final Announcer<AuctionEventListener> auctionEventListeners = Announcer.to(AuctionEventListener.class);
  private final Chat chat;
  private final XMPPFailureReporter failureReporter;
  
  public XMPPAuction(XMPPConnection connection, String auctionJID, XMPPFailureReporter failureReporter) { 
    this.failureReporter = failureReporter;
    AuctionMessageTranslator translator = translatorFor(connection);
    this.chat = connection.getChatManager().createChat( auctionJID, translator);
    addAuctionEventListener(chatDisconnectorFor(translator));
  }
  
  public void bid(int amount) { 
    sendMessage(String.format(BID_COMMAND_FORMAT, amount)); 
  } 
  public void join() { 
    sendMessage(JOIN_COMMAND_FORMAT); 
  } 
 
  public void addAuctionEventListener(AuctionEventListener listener) {
    auctionEventListeners.addListener(listener);
  }

  private AuctionMessageTranslator translatorFor(XMPPConnection connection) {
    return new AuctionMessageTranslator(connection.getUser(), auctionEventListeners.announce(), failureReporter);
  } 

  private AuctionEventListener 
  chatDisconnectorFor(final AuctionMessageTranslator translator) { 
    return new AuctionEventListener() { 
      public void auctionFailed() { 
        chat.removeMessageListener(translator); 
      }
      public void auctionClosed() { }
      public void currentPrice(int price, int increment, PriceSource priceSource) { }
    }; 
  } 
  private void sendMessage(final String message) { 
    try { 
      chat.sendMessage(message); 
    } catch (XMPPException e) { 
      e.printStackTrace(); 
    } 
  } 
  
} 


================================================
FILE: src/auctionsniper/xmpp/XMPPAuctionException.java
================================================
package auctionsniper.xmpp;

public class XMPPAuctionException extends Exception {

  public XMPPAuctionException(String message, Exception cause) {
    super(message, cause);
  }

}


================================================
FILE: src/auctionsniper/xmpp/XMPPAuctionHouse.java
================================================
package auctionsniper.xmpp;

import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import org.apache.commons.io.FilenameUtils;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

import auctionsniper.Auction;
import auctionsniper.AuctionHouse;
import auctionsniper.UserRequestListener.Item;

public class XMPPAuctionHouse implements AuctionHouse {
  private static final String LOGGER_NAME = "auction-sniper";
  public static final String LOG_FILE_NAME = "auction-sniper.log";
  public static final String ITEM_ID_AS_LOGIN = "auction-%s"; 
  public static final String AUCTION_ID_FORMAT = ITEM_ID_AS_LOGIN + "@%s/" + XMPPAuctionHouse.AUCTION_RESOURCE;
  public static final String AUCTION_RESOURCE = "Auction";
  
  private final XMPPConnection connection;
  private final LoggingXMPPFailureReporter failureReporter;
  
  public XMPPAuctionHouse(XMPPConnection connection) throws XMPPAuctionException {
    this.connection = connection;
    this.failureReporter = new LoggingXMPPFailureReporter(makeLogger());
  }

  public Auction auctionFor(Item item) {
    return new XMPPAuction(connection, auctionId(item.identifier, connection), failureReporter);
  }

  public void disconnect() {
    connection.disconnect();
  }

  public static XMPPAuctionHouse connect(String hostname, String username, String password) throws XMPPAuctionException {
    XMPPConnection connection = new XMPPConnection(hostname); 
    try {
      connection.connect(); 
      connection.login(username, password, AUCTION_RESOURCE); 
      return new XMPPAuctionHouse(connection);
    } catch (XMPPException xmppe) {
        throw new XMPPAuctionException("Could not connect to auction: " + connection, xmppe);
    }
  }
  
  private static String auctionId(String itemId, XMPPConnection connection) { 
    return String.format(AUCTION_ID_FORMAT, itemId, connection.getServiceName());
  }
  
  private Logger makeLogger() throws XMPPAuctionException { 
    Logger logger = Logger.getLogger(LOGGER_NAME); 
    logger.setUseParentHandlers(false); 
    logger.addHandler(simpleFileHandler()); 
    return logger; 
  }
  
  private FileHandler simpleFileHandler() throws XMPPAuctionException { 
    try { 
      FileHandler handler = new FileHandler(LOG_FILE_NAME); 
      handler.setFormatter(new SimpleFormatter()); 
      return handler; 
    } catch (Exception e) { 
      throw new XMPPAuctionException("Could not create logger FileHandler " 
                                   + FilenameUtils.getFullPath(LOG_FILE_NAME), e); 
    } 
  } 

}


================================================
FILE: src/auctionsniper/xmpp/XMPPFailureReporter.java
================================================
package auctionsniper.xmpp;

public interface XMPPFailureReporter { 
  void cannotTranslateMessage(String auctionId, String failedMessage, Exception exception);
}

================================================
FILE: test/end-to-end/test/endtoend/auctionsniper/ApplicationRunner.java
================================================
package test.endtoend.auctionsniper;

import static auctionsniper.ui.SnipersTableModel.textFor;
import static org.hamcrest.Matchers.containsString;
import static test.endtoend.auctionsniper.FakeAuctionServer.XMPP_HOSTNAME;

import java.io.IOException;

import javax.swing.SwingUtilities;

import auctionsniper.Main;
import auctionsniper.SniperState;
import auctionsniper.ui.MainWindow;

public class ApplicationRunner { 
  public static final String SNIPER_ID = "sniper"; 
  public static final String SNIPER_PASSWORD = "sniper";
  public static final String SNIPER_XMPP_ID = SNIPER_ID + "@" + XMPP_HOSTNAME + "/Auction";

  private AuctionLogDriver logDriver = new AuctionLogDriver();
  private AuctionSniperDriver driver; 
  
  public void startBiddingIn(final FakeAuctionServer... auctions) {
    startSniper(); 
    for (FakeAuctionServer auction : auctions) {
      openBiddingFor(auction, Integer.MAX_VALUE);
    }
  }
  public void startBiddingWithStopPrice(FakeAuctionServer auction, int stopPrice) {
    startSniper();
    openBiddingFor(auction, stopPrice);
  }  

  public void hasShownSniperHasLostAuction(FakeAuctionServer auction, int lastPrice, int lastBid) {
    driver.showsSniperStatus(auction.getItemId(), lastPrice, lastBid, textFor(SniperState.LOST));
  } 
  
  public void hasShownSniperIsBidding(FakeAuctionServer auction, int lastPrice, int lastBid) {
    driver.showsSniperStatus(auction.getItemId(), lastPrice, lastBid, textFor(SniperState.BIDDING));
  }

  public void hasShownSniperIsWinning(FakeAuctionServer auction, int winningBid) {
    driver.showsSniperStatus(auction.getItemId(), winningBid, winningBid, textFor(SniperState.WINNING));
  }

  public void hasShownSniperIsLosing(FakeAuctionServer auction, int lastPrice, int lastBid) {
    driver.showsSniperStatus(auction.getItemId(), lastPrice, lastBid, textFor(SniperState.LOSING));
  }

  public void hasShownSniperHasWonAuction(FakeAuctionServer auction, int lastPrice) {
    driver.showsSniperStatus(auction.getItemId(), lastPrice, lastPrice, textFor(SniperState.WON));
  }

  public void hasShownSniperHasFailed(FakeAuctionServer auction) {
    driver.showsSniperStatus(auction.getItemId(), 0, 0, textFor(SniperState.FAILED));
  }

  public void reportsInvalidMessage(FakeAuctionServer auction, String brokenMessage) throws IOException {
    logDriver.hasEntry(containsString(brokenMessage));
  }

  public void stop() { 
    if (driver != null) { 
      driver.dispose();  
    } 
  }

  private void startSniper() {
    logDriver.clearLog();
    Thread thread = new Thread("Test Application") { 
      @Override public void run() {  
        try { 
          Main.main(XMPP_HOSTNAME, SNIPER_ID, SNIPER_PASSWORD);
        } catch (Exception e) { 
          e.printStackTrace();  
        } 
      } 
    }; 
    thread.setDaemon(true); 
    thread.start(); 
    makeSureAwtIsLoadedBeforeStartingTheDriverOnOSXToStopDeadlock();
    
    driver = new AuctionSniperDriver(1000);  
    driver.hasTitle(MainWindow.APPLICATION_TITLE); 
    driver.hasColumnTitles();
  } 

  private void openBiddingFor(FakeAuctionServer auction, int stopPrice) {
    final String itemId = auction.getItemId();
    driver.startBiddingWithStopPrice(itemId, stopPrice);
    driver.showsSniperStatus(itemId, 0, 0, textFor(SniperState.JOINING));
  }

  private void makeSureAwtIsLoadedBeforeStartingTheDriverOnOSXToStopDeadlock() {
    try {
      SwingUtilities.invokeAndWait(new Runnable() { public void run() {} });
    } catch (Exception e) {
      throw new AssertionError(e);
    }
  }
} 


================================================
FILE: test/end-to-end/test/endtoend/auctionsniper/AuctionLogDriver.java
================================================
package test.endtoend.auctionsniper;

import static org.junit.Assert.assertThat;

import java.io.File;
import java.io.IOException;
import java.util.logging.LogManager;

import org.apache.commons.io.FileUtils;
import org.hamcrest.Matcher;

import auctionsniper.xmpp.XMPPAuctionHouse;

public class AuctionLogDriver { 
  private final File logFile = new File(XMPPAuctionHouse.LOG_FILE_NAME); 

  public void hasEntry(Matcher<String> matcher) throws IOException  { 
    assertThat(FileUtils.readFileToString(logFile), matcher); 
  } 

  public void clearLog() {
    logFile.delete();
    LogManager.getLogManager().reset(); 
  } 
} 


================================================
FILE: test/end-to-end/test/endtoend/auctionsniper/AuctionSniperDriver.java
================================================
package test.endtoend.auctionsniper;

import static auctionsniper.ui.MainWindow.NEW_ITEM_ID_NAME;
import static auctionsniper.ui.MainWindow.NEW_ITEM_STOP_PRICE_NAME;
import static com.objogate.wl.swing.matcher.IterableComponentsMatcher.matching;
import static com.objogate.wl.swing.matcher.JLabelTextMatcher.withLabelText;
import static java.lang.String.valueOf;

import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.table.JTableHeader;

import auctionsniper.ui.MainWindow;

import com.objogate.wl.swing.AWTEventQueueProber;
import com.objogate.wl.swing.driver.JButtonDriver;
import com.objogate.wl.swing.driver.JFrameDriver;
import com.objogate.wl.swing.driver.JTableDriver;
import com.objogate.wl.swing.driver.JTableHeaderDriver;
import com.objogate.wl.swing.driver.JTextFieldDriver;
import com.objogate.wl.swing.gesture.GesturePerformer;

@SuppressWarnings("unchecked")
public class AuctionSniperDriver extends JFrameDriver { 
  public AuctionSniperDriver(int timeoutMillis) { 
    super(new GesturePerformer(), 
          JFrameDriver.topLevelFrame( 
            named(MainWindow.MAIN_WINDOW_NAME), 
            showingOnScreen()), 
            new AWTEventQueueProber(timeoutMillis, 100)); 
  }
  
  public void hasColumnTitles() { 
    JTableHeaderDriver headers = new JTableHeaderDriver(this, 
                                                        JTableHeader.class); 
    headers.hasHeaders( 
       matching(withLabelText("Item"), withLabelText("Last Price"), 
                withLabelText("Last Bid"), withLabelText("State"))); 
  } 

  public void showsSniperStatus(String itemId, int lastPrice, int lastBid, String statusText) {
    JTableDriver table = new JTableDriver(this); 
    table.hasRow( 
        matching(withLabelText(itemId), withLabelText(valueOf(lastPrice)), 
               withLabelText(valueOf(lastBid)), withLabelText(statusText)));     
  }

  public void startBiddingWithStopPrice(String itemId, int stopPrice) {
    textField(NEW_ITEM_ID_NAME).replaceAllText(itemId); 
    textField(NEW_ITEM_STOP_PRICE_NAME).replaceAllText(String.valueOf(stopPrice)); 
    bidButton().click(); 
  }

  private JTextFieldDriver textField(String fieldName) {
    JTextFieldDriver newItemId = 
      new JTextFieldDriver(this, JTextField.class, named(fieldName));
    newItemId.focusWithMouse();
    return newItemId;
  }

  private JButtonDriver bidButton() {
    return new JButtonDriver(this, JButton.class, named(MainWindow.JOIN_BUTTON_NAME));
  } 
} 


================================================
FILE: test/end-to-end/test/endtoend/auctionsniper/AuctionSniperEndToEndTest.java
================================================
package test.endtoend.auctionsniper;

import org.junit.After;
import org.junit.Test;

public class AuctionSniperEndToEndTest { 
  private final FakeAuctionServer auction = new FakeAuctionServer("item-54321");
  private final FakeAuctionServer auction2 = new FakeAuctionServer("item-65432");  

  private final ApplicationRunner application = new ApplicationRunner(); 
  
  @Test public void 
  sniperJoinsAuctionUntilAuctionCloses() throws Exception { 
    auction.startSellingItem();                
    application.startBiddingIn(auction);       
    auction.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    auction.announceClosed();                  
    application.hasShownSniperHasLostAuction(auction, 0, 0);   
  } 

  
  @Test public void 
  sniperMakesAHigherBidButLoses() throws Exception { 
    auction.startSellingItem(); 
    
    application.startBiddingIn(auction); 
    auction.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID);
    auction.reportPrice(1000, 98, "other bidder");  
    application.hasShownSniperIsBidding(auction, 1000, 1098); 
    
    auction.hasReceivedBid(1098, ApplicationRunner.SNIPER_XMPP_ID);

    auction.announceClosed();                  
    application.hasShownSniperHasLostAuction(auction, 1000, 1098);   
  } 
  
  @Test public void 
  sniperWinsAnAuctionByBiddingHigher() throws Exception { 
    auction.startSellingItem(); 
    
    application.startBiddingIn(auction); 
    auction.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    auction.reportPrice(1000, 98, "other bidder"); 
    application.hasShownSniperIsBidding(auction, 1000, 1098); 
    
    auction.hasReceivedBid(1098, ApplicationRunner.SNIPER_XMPP_ID); 
    
    auction.reportPrice(1098, 97, ApplicationRunner.SNIPER_XMPP_ID); 
    application.hasShownSniperIsWinning(auction, 1098); 
    
    auction.announceClosed(); 
    application.hasShownSniperHasWonAuction(auction, 1098); 
  } 

  @Test public void 
  sniperBidsForMultipleItems() throws Exception { 
    auction.startSellingItem(); 
    auction2.startSellingItem(); 
    
    application.startBiddingIn(auction, auction2); 
    auction.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    auction2.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    
    auction.reportPrice(1000, 98, "other bidder"); 
    auction.hasReceivedBid(1098, ApplicationRunner.SNIPER_XMPP_ID);
    
    auction2.reportPrice(500, 21, "other bidder"); 
    auction2.hasReceivedBid(521, ApplicationRunner.SNIPER_XMPP_ID);
    
    auction.reportPrice(1098, 97, ApplicationRunner.SNIPER_XMPP_ID);    
    auction2.reportPrice(521, 22, ApplicationRunner.SNIPER_XMPP_ID); 
    
    application.hasShownSniperIsWinning(auction, 1098); 
    application.hasShownSniperIsWinning(auction2, 521);
    
    auction.announceClosed(); 
    auction2.announceClosed();
    
    application.hasShownSniperHasWonAuction(auction, 1098); 
    application.hasShownSniperHasWonAuction(auction2, 521); 
  } 

  @Test public void 
  sniperLosesAnAuctionWhenThePriceIsTooHigh() throws Exception { 
    auction.startSellingItem(); 
    
    application.startBiddingWithStopPrice(auction, 1100); 
    auction.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    auction.reportPrice(1000, 98, "other bidder"); 
    application.hasShownSniperIsBidding(auction, 1000, 1098);
    
    auction.hasReceivedBid(1098, ApplicationRunner.SNIPER_XMPP_ID); 
    
    auction.reportPrice(1197, 10, "third party"); 
    application.hasShownSniperIsLosing(auction, 1197, 1098); 
    
    auction.reportPrice(1207, 10, "fourth party"); 
    application.hasShownSniperIsLosing(auction, 1207, 1098); 
    auction.announceClosed(); 
    application.hasShownSniperHasLostAuction(auction, 1207, 1098); 
  } 

  @Test public void 
  sniperReportsInvalidAuctionMessageAndStopsRespondingToEvents() 
      throws Exception 
  { 
    String brokenMessage = "a broken message"; 
    auction.startSellingItem(); 
    auction2.startSellingItem();
    
    application.startBiddingIn(auction, auction2); 
    auction.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID);
    
    auction.reportPrice(500, 20, "other bidder"); 
    auction.hasReceivedBid(520, ApplicationRunner.SNIPER_XMPP_ID);
    
    auction.sendInvalidMessageContaining(brokenMessage); 
    application.hasShownSniperHasFailed(auction); 
    
    auction.reportPrice(520, 21, "other bidder"); 
    waitForAnotherAuctionEvent(); 
    
    application.reportsInvalidMessage(auction, brokenMessage); 
    application.hasShownSniperHasFailed(auction); 
  } 
  
  private void waitForAnotherAuctionEvent() throws Exception { 
    auction2.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    auction2.reportPrice(600, 6, "other bidder"); 
    application.hasShownSniperIsBidding(auction2, 600, 606); 
  } 

  @After public void stopAuction() { 
    auction.stop(); 
    auction2.stop();
  } 
  @After public void stopApplication() { 
    application.stop(); 
  } 
} 


================================================
FILE: test/end-to-end/test/endtoend/auctionsniper/FakeAuctionServer.java
================================================
package test.endtoend.auctionsniper;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.hamcrest.Matcher;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;

import auctionsniper.xmpp.XMPPAuction;

public class FakeAuctionServer {
  public static final String ITEM_ID_AS_LOGIN = "auction-%s";
  public static final String AUCTION_RESOURCE = "Auction";
  public static final String XMPP_HOSTNAME = "localhost";

  private static final String AUCTION_PASSWORD = "auction";
  private final SingleMessageListener messageListener = new SingleMessageListener();
  private final String itemId;
  private final XMPPConnection connection;

  private Chat currentChat;

  public FakeAuctionServer(String itemId) {
    this.itemId = itemId;
    this.connection = new XMPPConnection(XMPP_HOSTNAME);
  }

  public void startSellingItem() throws XMPPException {
    connection.connect();
    connection.login(String.format(ITEM_ID_AS_LOGIN, itemId), AUCTION_PASSWORD,
        AUCTION_RESOURCE);
    connection.getChatManager().addChatListener(new ChatManagerListener() {
      public void chatCreated(Chat chat, boolean createdLocally) {
        currentChat = chat;
        chat.addMessageListener(messageListener);
      }
    });
  }

  public void sendInvalidMessageContaining(String brokenMessage) throws XMPPException {
    currentChat.sendMessage(brokenMessage);
  } 

  public void reportPrice(int price, int increment, String bidder) throws XMPPException {
  currentChat.sendMessage( 
      String.format("SOLVersion: 1.1; Event: PRICE; " 
                    + "CurrentPrice: %d; Increment: %d; Bidder: %s;", 
                    price, increment, bidder)); 
  }
  
  public void hasReceivedJoinRequestFrom(String sniperId) throws InterruptedException {
    receivesAMessageMatching(sniperId, equalTo(XMPPAuction.JOIN_COMMAND_FORMAT)); 
  } 
  public void hasReceivedBid(int bid, String sniperId) throws InterruptedException {
    receivesAMessageMatching(sniperId, 
                           equalTo(String.format(XMPPAuction.BID_COMMAND_FORMAT, bid))); 
  } 
  
  private void receivesAMessageMatching(String sniperId, Matcher<? super String> messageMatcher) throws InterruptedException {
    messageListener.receivesAMessage(messageMatcher); 
    assertThat(currentChat.getParticipant(), equalTo(sniperId)); 
  } 
  
  public void announceClosed() throws XMPPException { 
    currentChat.sendMessage("SOLVersion: 1.1; Event: CLOSE;"); 
  } 

  public void stop() { 
    connection.disconnect(); 
  } 

  public String getItemId() {
    return itemId;
  }
  
  public class SingleMessageListener implements MessageListener { 
    private final ArrayBlockingQueue<Message> messages = 
                                new ArrayBlockingQueue<Message>(1); 
    public void processMessage(Chat chat, Message message) { 
      messages.add(message); 
    } 
    public void receivesAMessage() throws InterruptedException { 
      assertThat("Message", messages.poll(5, TimeUnit.SECONDS), is(notNullValue()));
    } 

    public void receivesAMessage(Matcher<? super String> messageMatcher) 
      throws InterruptedException 
    { 
      final Message message = messages.poll(5, TimeUnit.SECONDS); 
      assertThat(message, hasProperty("body", messageMatcher));
    } 
  }

}


================================================
FILE: test/integration/test/integration/auctionsniper/ui/MainWindowTest.java
================================================
package test.integration.auctionsniper.ui;

import static org.hamcrest.Matchers.equalTo;

import org.junit.Test;

import test.endtoend.auctionsniper.AuctionSniperDriver;
import auctionsniper.UserRequestListener;
import auctionsniper.SniperPortfolio;
import auctionsniper.UserRequestListener.Item;
import auctionsniper.ui.MainWindow;

import com.objogate.wl.swing.probe.ValueMatcherProbe;

public class MainWindowTest {
  private final MainWindow mainWindow = new MainWindow(new SniperPortfolio()); 
  private final AuctionSniperDriver driver = new AuctionSniperDriver(100); 
  
  @Test public void 
  makesUserRequestWhenJoinButtonClicked() { 
    final ValueMatcherProbe<Item> itemProbe = 
      new ValueMatcherProbe<Item>(equalTo(new Item("an item-id", 789)), 
                                  "item request");
    mainWindow.addUserRequestListener( 
        new UserRequestListener() { 
          public void joinAuction(Item item) { 
            itemProbe.setReceivedValue(item); 
          } 
        }); 
    
    driver.startBiddingWithStopPrice("an item-id", 789);
    driver.check(itemProbe); 
  }
}


================================================
FILE: test/integration/test/integration/auctionsniper/xmpp/XMPPAuctionHouseTest.java
================================================
package test.integration.auctionsniper.xmpp;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertTrue;

import java.util.concurrent.CountDownLatch;

import org.jivesoftware.smack.XMPPException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import test.endtoend.auctionsniper.ApplicationRunner;
import test.endtoend.auctionsniper.FakeAuctionServer;
import auctionsniper.Auction;
import auctionsniper.AuctionEventListener;
import auctionsniper.UserRequestListener.Item;
import auctionsniper.xmpp.XMPPAuctionException;
import auctionsniper.xmpp.XMPPAuctionHouse;

public class XMPPAuctionHouseTest {
  private final FakeAuctionServer auctionServer = new FakeAuctionServer("item-54321");  
  private XMPPAuctionHouse auctionHouse; 

  @Before public void openConnection() throws XMPPAuctionException {
    auctionHouse = XMPPAuctionHouse.connect(FakeAuctionServer.XMPP_HOSTNAME, ApplicationRunner.SNIPER_ID, ApplicationRunner.SNIPER_PASSWORD);
    
  }
  @After public void closeConnection() {
    if (auctionHouse != null) {
      auctionHouse.disconnect();
    }
  }
  @Before public void startAuction() throws XMPPException {
    auctionServer.startSellingItem();
  }
  @After public void stopAuction() {
    auctionServer.stop();
  }


  @Test public void 
  receivesEventsFromAuctionServerAfterJoining() throws Exception { 
    CountDownLatch auctionWasClosed = new CountDownLatch(1); 
    
    Auction auction = auctionHouse.auctionFor(new Item(auctionServer.getItemId(), 567));
    auction.addAuctionEventListener(auctionClosedListener(auctionWasClosed));
    auction.join(); 
    auctionServer.hasReceivedJoinRequestFrom(ApplicationRunner.SNIPER_XMPP_ID); 
    auctionServer.announceClosed(); 
    
    assertTrue("should have been closed", auctionWasClosed.await(4, SECONDS)); 
  } 

  private AuctionEventListener 
  auctionClosedListener(final CountDownLatch auctionWasClosed) { 
    return new AuctionEventListener() { 
      public void auctionClosed() { 
        auctionWasClosed.countDown(); 
      } 
      public void currentPrice(int price, int increment, PriceSource priceSource) { }
      public void auctionFailed() { }
    }; 
  }
}


================================================
FILE: test/unit/test/auctionsniper/AuctionSniperTest.java
================================================
package test.auctionsniper;

import static auctionsniper.SniperState.BIDDING;
import static auctionsniper.SniperState.LOSING;
import static auctionsniper.SniperState.LOST;
import static auctionsniper.SniperState.WINNING;
import static auctionsniper.SniperState.WON;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.samePropertyValuesAs;
import static org.junit.Assert.assertThat;

import org.hamcrest.FeatureMatcher;
import org.hamcrest.Matcher;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.Sequence;
import org.jmock.States;
import org.jmock.integration.junit4.JMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import auctionsniper.Auction;
import auctionsniper.AuctionSniper;
import auctionsniper.SniperListener;
import auctionsniper.SniperSnapshot;
import auctionsniper.SniperState;
import auctionsniper.AuctionEventListener.PriceSource;
import auctionsniper.UserRequestListener.Item;

@RunWith(JMock.class) 
public class AuctionSniperTest { 
  protected static final String ITEM_ID = "item-id";
  public static final Item ITEM = new Item(ITEM_ID, 1234);
  private final Mockery context = new Mockery(); 
  private final States sniperState = context.states("sniper");
  private final Auction auction = context.mock(Auction.class);
  private final SniperListener sniperListener = context.mock(SniperListener.class);
  private final AuctionSniper sniper = new AuctionSniper(ITEM, auction); 
  
  @Before public void attachListener() {
    sniper.addSniperListener(sniperListener);
  }
  
  @Test public void
  hasInitialStateOfJoining() {
    assertThat(sniper.getSnapshot(), samePropertyValuesAs(SniperSnapshot.joining(ITEM_ID)));
  }
  
  @Test public void 
  reportsLostWhenAuctionClosesImmediately() { 
    context.checking(new Expectations() {{ 
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, 0, 0, LOST));  
    }}); 
    
    sniper.auctionClosed(); 
  }
  
  @Test public void 
  bidsHigherAndReportsBiddingWhenNewPriceArrives() { 
    final int price = 1001; 
    final int increment = 25; 
    final int bid = price + increment;
    context.checking(new Expectations() {{ 
      one(auction).bid(bid); 
      
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, price, bid, BIDDING)); 
    }}); 
    
    sniper.currentPrice(price, increment, PriceSource.FromOtherBidder); 
  } 
  

  @Test public void
  doesNotBidAndReportsLosingIfFirstPriceIsAboveStopPrice() {
    final int price = 1233;
    final int increment = 25;

    context.checking(new Expectations() {{
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, price, 0, LOSING));
    }});
    
    sniper.currentPrice(price, increment, PriceSource.FromOtherBidder);
  }

  @Test public void
  doesNotBidAndReportsLosingIfSubsequentPriceIsAboveStopPrice() {
    allowingSniperBidding();
    context.checking(new Expectations() {{
      int bid = 123 + 45;
      allowing(auction).bid(bid);
      
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, 2345, bid, LOSING)); when(sniperState.is("bidding"));
    }});
   
    sniper.currentPrice(123, 45, PriceSource.FromOtherBidder);
    sniper.currentPrice(2345, 25, PriceSource.FromOtherBidder);
  }
  
  @Test public void
  doesNotBidAndReportsLosingIfPriceAfterWinningIsAboveStopPrice() {
    final int price = 1233;
    final int increment = 25;

    allowingSniperBidding();
    allowingSniperWinning();
    context.checking(new Expectations() {{
      int bid = 123 + 45;
      allowing(auction).bid(bid);
      
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, price, bid, LOSING)); when(sniperState.is("winning"));
    }});
   
    sniper.currentPrice(123, 45, PriceSource.FromOtherBidder);
    sniper.currentPrice(168, 45, PriceSource.FromSniper);
    sniper.currentPrice(price, increment, PriceSource.FromOtherBidder);
  }

  @Test public void
  continuesToBeLosingOnceStopPriceHasBeenReached() {
    final Sequence states = context.sequence("sniper states");
    final int price1 = 1233;
    final int price2 = 1258;

    context.checking(new Expectations() {{
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, price1, 0, LOSING)); inSequence(states);
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, price2, 0, LOSING)); inSequence(states);
    }});
   
    sniper.currentPrice(price1, 25, PriceSource.FromOtherBidder);
    sniper.currentPrice(price2, 25, PriceSource.FromOtherBidder);
  }

  @Test public void 
  reportsLostIfAuctionClosesWhenBidding() { 
    allowingSniperBidding();
    ignoringAuction();
    
    context.checking(new Expectations() {{ 
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, 123, 168, LOST)); 
                                                                    when(sniperState.is("bidding")); 
    }}); 
    
    sniper.currentPrice(123, 45, PriceSource.FromOtherBidder); 
    sniper.auctionClosed(); 
  } 
  
  @Test public void
  reportsLostIfAuctionClosesWhenLosing() {
    allowingSniperLosing();
    context.checking(new Expectations() {{
      atLeast(1).of(sniperListener).sniperStateChanged(new SniperSnapshot(ITEM_ID, 1230, 0, LOST)); 
                                                                    when(sniperState.is("losing"));
    }});
    
    sniper.currentPrice(1230, 456, PriceSource.FromOtherBidder);
    sniper.auctionClosed();
  }



  @Test public void 
  reportsIsWinningWhenCurrentPriceComesFromSniper() { 
    allowingSniperBidding();
    ignoringAuction();
    context.checking(new Expectations() {{ 
      atLeast(1).of(sniperListener).sniperStateChanged( new SniperSnapshot(ITEM_ID, 135, 135, WINNING)); when(sniperState.is("bidding"));
    }}); 
    
    sniper.currentPrice(123, 12, PriceSource.FromOtherBidder);
    sniper.currentPrice(135, 45, PriceSource.FromSniper); 
  } 
  
  @Test public void 
  reportsWonIfAuctionClosesWhenWinning() { 
    allowingSniperBidding();
    allowingSniperWinning();
    ignoringAuction();
    
    context.checking(new Expectations() {{ 
      atLeast(1).of(sniperListener).sniperStateChanged( new SniperSnapshot(ITEM_ID, 135, 135, WON)); when(sniperState.is("winning"));
    }}); 
    
    sniper.currentPrice(123, 12, PriceSource.FromOtherBidder);
    sniper.currentPrice(135, 45, PriceSource.FromSniper); 
    sniper.auctionClosed(); 
  } 

  @Test public void 
  reportsFailedIfAuctionFailsWhenBidding() { 
    ignoringAuction();
    allowingSniperBidding();
    
    expectSniperToFailWhenItIs("bidding");
    
    sniper.currentPrice(123, 45, PriceSource.FromOtherBidder); 
    sniper.auctionFailed(); 
  } 
  
  @Test public void
  reportsFailedIfAuctionFailsImmediately() {
    context.checking(new Expectations() {{
      atLeast(1).of(sniperListener).sniperStateChanged(SniperSnapshot.joining(ITEM_ID).failed());
    }});
    
    sniper.auctionFailed();
  }

  @Test public void
  reportsFailedIfAuctionFailsWhenLosing() {
    allowingSniperLosing();

    expectSniperToFailWhenItIs("losing");
    
    sniper.currentPrice(1230, 456, PriceSource.FromOtherBidder);
    sniper.auctionFailed();
  }


  @Test public void
  reportsFailedIfAuctionFailsWhenWinning() {
    ignoringAuction();
    allowingSniperBidding();
    allowingSniperWinning();
    
    expectSniperToFailWhenItIs("winning");
    
    sniper.currentPrice(123, 12, PriceSource.FromOtherBidder);
    sniper.currentPrice(135, 45, PriceSource.FromSniper);
    sniper.auctionFailed();
  }


  private void expectSniperToFailWhenItIs(final String state) {
    context.checking(new Expectations() {{
      atLeast(1).of(sniperListener).sniperStateChanged(
          new SniperSnapshot(ITEM_ID, 00, 0, SniperState.FAILED)); 
                                      when(sniperState.is(state));
    }});
  }
  private void ignoringAuction() {
    context.checking(new Expectations() {{ 
      ignoring(auction);
    }});
  }
  private void allowingSniperBidding() {
    allowSniperStateChange(BIDDING, "bidding");
  }

  private void allowingSniperLosing() {
    allowSniperStateChange(LOSING, "losing");
  }

  private void allowingSniperWinning() {
    allowSniperStateChange(WINNING, "winning");
  }

  private void allowSniperStateChange(final SniperState newState, final String oldState) {
    context.checking(new Expectations() {{ 
      allowing(sniperListener).sniperStateChanged(with(aSniperThatIs(newState))); then(sniperState.is(oldState));
    }});
  }

  private Matcher<SniperSnapshot> aSniperThatIs(final SniperState state) { 
    return new FeatureMatcher<SniperSnapshot, SniperState>( equalTo(state), "sniper that is ", "was") {
      @Override 
      protected SniperState featureValueOf(SniperSnapshot actual) { 
        return actual.state; 
      } 
    }; 
  } 
} 


================================================
FILE: test/unit/test/auctionsniper/SniperLauncherTest.java
================================================
package test.auctionsniper;

import static org.hamcrest.Matchers.equalTo;

import org.hamcrest.FeatureMatcher;
import org.hamcrest.Matcher;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.States;
import org.jmock.integration.junit4.JMock;
import org.junit.Test;
import org.junit.runner.RunWith;

import auctionsniper.Auction;
import auctionsniper.AuctionHouse;
import auctionsniper.AuctionSniper;
import auctionsniper.SniperCollector;
import auctionsniper.SniperLauncher;
import auctionsniper.UserRequestListener.Item;

@RunWith(JMock.class)
public class SniperLauncherTest {
  private final Mockery context = new Mockery();
  private final States auctionState = context.states("auction state").startsAs("not joined");
  private final Auction auction = context.mock(Auction.class);
  private final AuctionHouse auctionHouse = context.mock(AuctionHouse.class);
  private final SniperCollector sniperCollector = context.mock(SniperCollector.class);
  private final SniperLauncher launcher = new SniperLauncher(auctionHouse, sniperCollector);
  
  @Test public void
  addsNewSniperToCollectorAndThenJoinsAuction() {
    final Item item = new Item("item 123", 456);

    context.checking(new Expectations() {{
      allowing(auctionHouse).auctionFor(item); will(returnValue(auction));
      
      oneOf(auction).addAuctionEventListener(with(sniperForItem(item))); when(auctionState.is("not joined"));
      oneOf(sniperCollector).addSniper(with(sniperForItem(item))); when(auctionState.is("not joined"));
      
      one(auction).join(); then(auctionState.is("joined"));
    }});
    
    launcher.joinAuction(item);
  }

  protected Matcher<AuctionSniper>sniperForItem(Item item) {
    return new FeatureMatcher<AuctionSniper, String>(equalTo(item.identifier), "sniper with item id", "item") {
      @Override protected String featureValueOf(AuctionSniper actual) {
        return actual.getSnapshot().itemId;
      }
    };
  }
}


================================================
FILE: test/unit/test/auctionsniper/SniperPortfolioTest.java
================================================
package test.auctionsniper;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.junit.Test;
import org.junit.runner.RunWith;

import auctionsniper.AuctionSniper;
import auctionsniper.SniperPortfolio;
import auctionsniper.UserRequestListener.Item;
import auctionsniper.SniperPortfolio.PortfolioListener;

@RunWith(JMock.class)
public class SniperPortfolioTest {
  private final Mockery context = new Mockery();
  private final PortfolioListener listener = context.mock(PortfolioListener.class);
  private final SniperPortfolio portfolio = new SniperPortfolio();
  
  @Test public void
  notifiesListenersOfNewSnipers() {
    final AuctionSniper sniper = new AuctionSniper(new Item("item id", 123), null);
    context.checking(new Expectations() {{
      oneOf(listener).sniperAdded(sniper);
    }});
    portfolio.addPortfolioListener(listener);
    
    portfolio.addSniper(sniper);
  }
}


================================================
FILE: test/unit/test/auctionsniper/SniperSnapshotTest.java
================================================
package test.auctionsniper;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import auctionsniper.SniperSnapshot;
import auctionsniper.SniperState;

public class SniperSnapshotTest {

  @Test public void
  transitionsBetweenStates() {
    final String itemId = "item id";
    SniperSnapshot joining = SniperSnapshot.joining(itemId);
    
    assertEquals(new SniperSnapshot(itemId, 0, 0, SniperState.JOINING),
        joining);
    
    SniperSnapshot bidding = joining.bidding(123, 234);
    assertEquals(
        new SniperSnapshot(itemId, 123, 234, SniperState.BIDDING),
        bidding);  

    assertEquals(new SniperSnapshot(itemId, 456, 234, SniperState.LOSING),
                 bidding.losing(456));
    
    assertEquals(
        new SniperSnapshot(itemId, 456, 234, SniperState.WINNING),
        bidding.winning(456));  

    assertEquals(
        new SniperSnapshot(itemId, 123, 234, SniperState.LOST),
        bidding.closed());  

    assertEquals(
        new SniperSnapshot(itemId, 678, 234, SniperState.WON),
        bidding.winning(678).closed());  
  }
  
  @Test public void
  comparesItemIdentities() {
    assertTrue(
        SniperSnapshot.joining("item 1").isForSameItemAs(
            SniperSnapshot.joining("item 1")));
    assertFalse(
        SniperSnapshot.joining("item 1").isForSameItemAs(
            SniperSnapshot.joining("item 2")));
  }
}


================================================
FILE: test/unit/test/auctionsniper/SniperStateTests.java
================================================
package test.auctionsniper;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import auctionsniper.SniperState;
import auctionsniper.util.Defect;

public class SniperStateTests {

  @Test public void
  isWonWhenAuctionClosesWhileWinning() {
    assertEquals(SniperState.LOST, SniperState.JOINING.whenAuctionClosed());
    assertEquals(SniperState.LOST, SniperState.BIDDING.whenAuctionClosed());
    assertEquals(SniperState.WON, SniperState.WINNING.whenAuctionClosed());
  }
  
  @Test(expected=Defect.class) public void
  defectIfAuctionClosesWhenWon() {
    SniperState.WON.whenAuctionClosed();
  }

  @Test(expected=Defect.class) public void
  defectIfAuctionClosesWhenLost() {
    SniperState.LOST.whenAuctionClosed();
  }

}


================================================
FILE: test/unit/test/auctionsniper/ui/ColumnTest.java
================================================
package test.auctionsniper.ui;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import auctionsniper.SniperSnapshot;
import auctionsniper.SniperState;
import auctionsniper.ui.Column;

public class ColumnTest {

  @Test public void
  retrievesValuesFromASniperSnapshot() {
    SniperSnapshot snapshot = new SniperSnapshot("item", 123, 34, SniperState.BIDDING);
    assertEquals("item", Column.ITEM_IDENTIFIER.valueIn(snapshot));
    assertEquals(123, Column.LAST_PRICE.valueIn(snapshot));
    assertEquals(34, Column.LAST_BID.valueIn(snapshot));
    assertEquals("Bidding", Column.SNIPER_STATE.valueIn(snapshot));
  }
}


================================================
FILE: test/unit/test/auctionsniper/ui/SnipersTableModelTest.java
================================================
package test.auctionsniper.ui;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.samePropertyValuesAs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import org.hamcrest.Matcher;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import auctionsniper.AuctionSniper;
import auctionsniper.SniperSnapshot;
import auctionsniper.SniperState;
import auctionsniper.UserRequestListener.Item;
import auctionsniper.ui.Column;
import auctionsniper.ui.SnipersTableModel;
import auctionsniper.util.Defect;

@RunWith(JMock.class) 
public class SnipersTableModelTest { 
  private static final String ITEM_ID = "item 0";
  private final Mockery context = new Mockery(); 
  private TableModelListener listener = context.mock(TableModelListener.class); 
  private final SnipersTableModel model = new SnipersTableModel();
  private final AuctionSniper sniper = new AuctionSniper(new Item(ITEM_ID, 234), null); 
  
  @Before public void attachModelListener() {
    model.addTableModelListener(listener); 
  } 
  
  @Test public void 
  hasEnoughColumns() { 
    assertThat(model.getColumnCount(), equalTo(Column.values().length)); 
  }
  
  @Test public void 
  setsUpColumnHeadings() { 
    for (Column column: Column.values()) { 
      assertEquals(column.name, model.getColumnName(column.ordinal())); 
    } 
  } 
  
  @Test public void
  acceptsNewSniper() {
    context.checking(new Expectations() {{
      one(listener).tableChanged(with(anInsertionAtRow(0)));
    }});

    model.sniperAdded(sniper);
    
    assertRowMatchesSnapshot(0, SniperSnapshot.joining(ITEM_ID));
  }
  
  @Test public void 
  setsSniperValuesInColumns() { 
    SniperSnapshot bidding = sniper.getSnapshot().bidding(555, 666);
    context.checking(new Expectations() {{ 
      allowing(listener).tableChanged(with(anyInsertionEvent()));
      
      one(listener).tableChanged(with(aChangeInRow(0))); 
    }}); 

    model.sniperAdded(sniper);
    model.sniperStateChanged(bidding);
    
    assertRowMatchesSnapshot(0, bidding);
  } 
  
  @Test public void
  notifiesListenersWhenAddingASniper() {
    context.checking(new Expectations() { {
      one(listener).tableChanged(with(anInsertionAtRow(0)));
    }});

    assertEquals(0, model.getRowCount());
    
    model.sniperAdded(sniper);
    
    assertEquals(1, model.getRowCount());
    assertRowMatchesSnapshot(0, SniperSnapshot.joining(ITEM_ID));
  }
  
  @Test public void 
  holdsSnipersInAdditionOrder() {
    AuctionSniper sniper2 = new AuctionSniper(new Item("item 1", 345), null);
    context.checking(new Expectations() { {
      ignoring(listener);
    }});
    
    model.sniperAdded(sniper);
    model.sniperAdded(sniper2);
    
    assertEquals(ITEM_ID, cellValue(0, Column.ITEM_IDENTIFIER));
    assertEquals("item 1", cellValue(1, Column.ITEM_IDENTIFIER));
  }
  
  @Test public void 
  updatesCorrectRowForSniper() {
    AuctionSniper sniper2 = new AuctionSniper(new Item("item 1", 345), null);
    context.checking(new Expectations() { {
      allowing(listener).tableChanged(with(anyInsertionEvent()));

      one(listener).tableChanged(with(aChangeInRow(1)));
    }});
    
    model.sniperAdded(sniper);
    model.sniperAdded(sniper2);

    SniperSnapshot winning1 = sniper2.getSnapshot().winning(123);
    model.sniperStateChanged(winning1);
    
    assertRowMatchesSnapshot(1, winning1);
  }

  @Test(expected=Defect.class) public void
  throwsDefectIfNoExistingSniperForAnUpdate() {
    model.sniperStateChanged(new SniperSnapshot("item 1", 123, 234, SniperState.WINNING));
  }
  
  private void assertRowMatchesSnapshot(int row, SniperSnapshot snapshot) {
    assertEquals(snapshot.itemId, cellValue(row, Column.ITEM_IDENTIFIER));
    assertEquals(snapshot.lastPrice, cellValue(row, Column.LAST_PRICE));
    assertEquals(snapshot.lastBid, cellValue(row, Column.LAST_BID));
    assertEquals(SnipersTableModel.textFor(snapshot.state), cellValue(row, Column.SNIPER_STATE));
  }

  private Object cellValue(int rowIndex, Column column) {
    return model.getValueAt(rowIndex, column.ordinal());
  }

  Matcher<TableModelEvent> anyInsertionEvent() {
    return hasProperty("type", equalTo(TableModelEvent.INSERT));
  }
  Matcher<TableModelEvent> anInsertionAtRow(final int row) {
    return samePropertyValuesAs(new TableModelEvent(model, row, row, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }

  private Matcher<TableModelEvent> aChangeInRow(int row) { 
    return samePropertyValuesAs(new TableModelEvent(model, row)); 
  } 
  
} 


================================================
FILE: test/unit/test/auctionsniper/xmpp/AuctionMessageTranslatorTest.java
================================================
package test.auctionsniper.xmpp;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.packet.Message;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.junit.Test;
import org.junit.runner.RunWith;

import auctionsniper.AuctionEventListener;
import auctionsniper.AuctionEventListener.PriceSource;
import auctionsniper.xmpp.AuctionMessageTranslator;
import auctionsniper.xmpp.XMPPFailureReporter;

@RunWith(JMock.class) 
public class AuctionMessageTranslatorTest { 
  private static final String SNIPER_ID = "sniper id";
  private static final Chat UNUSED_CHAT = null;
  
  private final Mockery context = new Mockery(); 
  private final XMPPFailureReporter failureReporter = context.mock(XMPPFailureReporter.class);
  private final AuctionEventListener listener = context.mock(AuctionEventListener.class);
  private final AuctionMessageTranslator translator = new AuctionMessageTranslator(SNIPER_ID, listener, failureReporter);
  
  @Test public void 
  notifiesAuctionClosedWhenCloseMessageReceived() { 
    context.checking(new Expectations() {{ 
      exactly(1).of(listener).auctionClosed(); 
    }}); 
  
    Message message = new Message(); 
    message.setBody("SOLVersion: 1.1; Event: CLOSE;"); 
    
    translator.processMessage(UNUSED_CHAT, message); 
  } 
  
  @Test public void 
  notifiesBidDetailsWhenCurrentPriceMessageReceivedFromOtherBidder() { 
    context.checking(new Expectations() {{ 
      exactly(1).of(listener).currentPrice(192, 7, PriceSource.FromOtherBidder); 
    }}); 
    
    Message message = new Message(); 
    message.setBody("SOLVersion: 1.1; Event: PRICE; CurrentPrice: 192; Increment: 7; Bidder: Someone else;");
    
    translator.processMessage(UNUSED_CHAT, message); 
  } 

  @Test public void 
  notifiesBidDetailsWhenCurrentPriceMessageReceivedFromSniper() { 
    context.checking(new Expectations() {{ 
      exactly(1).of(listener).currentPrice(192, 7, PriceSource.FromSniper); 
    }}); 
    
    Message message = new Message(); 
    message.setBody("SOLVersion: 1.1; Event: PRICE; CurrentPrice: 192; Increment: 7; Bidder: "
                    + SNIPER_ID + ";");
    
    translator.processMessage(UNUSED_CHAT, message); 
  } 

  @Test public void 
  notifiesAuctionFailedWhenBadMessageReceived() { 
    String badMessage = "a bad message";
    expectFailureWithMessage(badMessage);
    
    translator.processMessage(UNUSED_CHAT, message(badMessage)); 
  } 

  @Test public void 
  notifiesAuctionFailedWhenEventTypeMissing() { 
    String badMessage = "SOLVersion: 1.1; CurrentPrice: 234; Increment: 5; Bidder: " + SNIPER_ID + ";";
    expectFailureWithMessage(badMessage);

    translator.processMessage(UNUSED_CHAT, message(badMessage)); 
  } 

  private Message message(String body) { 
    Message message = new Message(); 
    message.setBody(body); 
    return message; 
  } 
  
  private void expectFailureWithMessage(final String badMessage) { 
    context.checking(new Expectations() {{  
      oneOf(listener).auctionFailed(); 
      oneOf(failureReporter).cannotTranslateMessage( 
                               with(SNIPER_ID), with(badMessage), 
                               with(any(Exception.class))); 
    }}); 
  } 

} 


================================================
FILE: test/unit/test/auctionsniper/xmpp/LoggingXMPPFailureReporterTest.java
================================================
package test.auctionsniper.xmpp;

import java.util.logging.LogManager;
import java.util.logging.Logger;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import auctionsniper.xmpp.LoggingXMPPFailureReporter;

@RunWith(JMock.class) 
public class LoggingXMPPFailureReporterTest { 
  private final Mockery context = new Mockery() {{ 
    setImposteriser(ClassImposteriser.INSTANCE); 
  }}; 
  final Logger logger = context.mock(Logger.class); 
  final LoggingXMPPFailureReporter reporter = new LoggingXMPPFailureReporter(logger);
  
  @AfterClass public static void resetLogging() { 
    LogManager.getLogManager().reset(); 
  } 
  @Test public void 
  writesMessageTranslationFailureToLog() { 
    context.checking(new Expectations() {{ 
      oneOf(logger).severe("<auction id> " 
                         + "Could not translate message \"bad message\" " 
                         + "because \"java.lang.Exception: an exception\""); 
    }}); 
    
    reporter.cannotTranslateMessage("auction id", "bad message", 
                                    new Exception("an exception")); 
  } 
} 


================================================
FILE: tools/openfire-version-is-3.6.txt
================================================
Download .txt
gitextract_xhlrihb_/

├── .classpath
├── .project
├── build.xml
├── lib/
│   ├── deploy/
│   │   ├── commons-io-1.4.jar
│   │   ├── commons-lang-2.4.jar
│   │   ├── smack_3_1_0.jar
│   │   └── smackx_3_1_0.jar
│   └── develop/
│       ├── cglib-nodep-2.2.jar
│       ├── commons-io-1.4-sources.jar
│       ├── commons-lang-2.4-sources.jar
│       ├── hamcrest-core-1.2.jar
│       ├── hamcrest-core-SNAPSHOT.jar
│       ├── hamcrest-library-1.2.jar
│       ├── hamcrest-library-SNAPSHOT.jar
│       ├── jmock-2.6-SNAPSHOT.jar
│       ├── jmock-junit4-2.6-SNAPSHOT.jar
│       ├── jmock-legacy-2.6-SNAPSHOT.jar
│       ├── junit-4.6-src.jar
│       ├── junit-dep-4.6.jar
│       ├── objenesis-1.0.jar
│       ├── windowlicker-core-DEV.jar
│       └── windowlicker-swing-DEV.jar
├── license.txt
├── src/
│   └── auctionsniper/
│       ├── Auction.java
│       ├── AuctionEventListener.java
│       ├── AuctionHouse.java
│       ├── AuctionSniper.java
│       ├── Main.java
│       ├── SniperCollector.java
│       ├── SniperLauncher.java
│       ├── SniperListener.java
│       ├── SniperPortfolio.java
│       ├── SniperSnapshot.java
│       ├── SniperState.java
│       ├── UserRequestListener.java
│       ├── ui/
│       │   ├── Column.java
│       │   ├── MainWindow.java
│       │   ├── SnipersTableModel.java
│       │   └── SwingThreadSniperListener.java
│       ├── util/
│       │   ├── Announcer.java
│       │   └── Defect.java
│       └── xmpp/
│           ├── AuctionMessageTranslator.java
│           ├── LoggingXMPPFailureReporter.java
│           ├── XMPPAuction.java
│           ├── XMPPAuctionException.java
│           ├── XMPPAuctionHouse.java
│           └── XMPPFailureReporter.java
├── test/
│   ├── end-to-end/
│   │   └── test/
│   │       └── endtoend/
│   │           └── auctionsniper/
│   │               ├── ApplicationRunner.java
│   │               ├── AuctionLogDriver.java
│   │               ├── AuctionSniperDriver.java
│   │               ├── AuctionSniperEndToEndTest.java
│   │               └── FakeAuctionServer.java
│   ├── integration/
│   │   └── test/
│   │       └── integration/
│   │           └── auctionsniper/
│   │               ├── ui/
│   │               │   └── MainWindowTest.java
│   │               └── xmpp/
│   │                   └── XMPPAuctionHouseTest.java
│   └── unit/
│       └── test/
│           └── auctionsniper/
│               ├── AuctionSniperTest.java
│               ├── SniperLauncherTest.java
│               ├── SniperPortfolioTest.java
│               ├── SniperSnapshotTest.java
│               ├── SniperStateTests.java
│               ├── ui/
│               │   ├── ColumnTest.java
│               │   └── SnipersTableModelTest.java
│               └── xmpp/
│                   ├── AuctionMessageTranslatorTest.java
│                   └── LoggingXMPPFailureReporterTest.java
└── tools/
    └── openfire-version-is-3.6.txt
Download .txt
SYMBOL INDEX (265 symbols across 40 files)

FILE: src/auctionsniper/Auction.java
  type Auction (line 3) | public interface Auction {
    method join (line 5) | void join();
    method bid (line 6) | void bid(int amount);
    method addAuctionEventListener (line 7) | void addAuctionEventListener(AuctionEventListener listener);

FILE: src/auctionsniper/AuctionEventListener.java
  type AuctionEventListener (line 5) | public interface AuctionEventListener extends EventListener {
    type PriceSource (line 6) | enum PriceSource {
    method auctionClosed (line 10) | void auctionClosed();
    method currentPrice (line 11) | void currentPrice(int price, int increment, PriceSource priceSource);
    method auctionFailed (line 12) | void auctionFailed();

FILE: src/auctionsniper/AuctionHouse.java
  type AuctionHouse (line 5) | public interface AuctionHouse {
    method auctionFor (line 6) | Auction auctionFor(Item item);

FILE: src/auctionsniper/AuctionSniper.java
  class AuctionSniper (line 6) | public class AuctionSniper implements AuctionEventListener {
    method AuctionSniper (line 12) | public AuctionSniper(Item item, Auction auction) {
    method addSniperListener (line 18) | public void addSniperListener(SniperListener listener) {
    method auctionClosed (line 22) | public void auctionClosed() {
    method auctionFailed (line 27) | public void auctionFailed() {
    method currentPrice (line 32) | public void currentPrice(int price, int increment, PriceSource priceSo...
    method getSnapshot (line 50) | public SniperSnapshot getSnapshot() {
    method notifyChange (line 54) | private void notifyChange() {

FILE: src/auctionsniper/Main.java
  class Main (line 11) | public class Main {
    method Main (line 20) | public Main() throws Exception {
    method main (line 24) | public static void main(String... args) throws Exception {
    method startUserInterface (line 31) | private void startUserInterface() throws Exception {
    method disconnectWhenUICloses (line 39) | private void disconnectWhenUICloses(final XMPPAuctionHouse auctionHous...
    method addUserRequestListenerFor (line 47) | private void addUserRequestListenerFor(final AuctionHouse auctionHouse) {

FILE: src/auctionsniper/SniperCollector.java
  type SniperCollector (line 3) | public interface SniperCollector {
    method addSniper (line 4) | void addSniper(AuctionSniper sniper);

FILE: src/auctionsniper/SniperLauncher.java
  class SniperLauncher (line 4) | public class SniperLauncher implements UserRequestListener {
    method SniperLauncher (line 8) | public SniperLauncher(AuctionHouse auctionHouse, SniperCollector colle...
    method joinAuction (line 13) | public void joinAuction(Item item) {

FILE: src/auctionsniper/SniperListener.java
  type SniperListener (line 5) | public interface SniperListener extends EventListener {
    method sniperStateChanged (line 6) | void sniperStateChanged(SniperSnapshot snapshot);

FILE: src/auctionsniper/SniperPortfolio.java
  class SniperPortfolio (line 8) | public class SniperPortfolio implements SniperCollector {
    type PortfolioListener (line 9) | public interface PortfolioListener extends EventListener {
      method sniperAdded (line 10) | void sniperAdded(AuctionSniper sniper);
    method addSniper (line 16) | public void addSniper(AuctionSniper sniper) {
    method addPortfolioListener (line 21) | public void addPortfolioListener(PortfolioListener listener) {

FILE: src/auctionsniper/SniperSnapshot.java
  class SniperSnapshot (line 7) | public class SniperSnapshot {
    method SniperSnapshot (line 13) | public SniperSnapshot(String itemId, int lastPrice, int lastBid, Snipe...
    method equals (line 20) | @Override
    method hashCode (line 24) | @Override
    method toString (line 28) | @Override
    method joining (line 33) | public static SniperSnapshot joining(String itemId) {
    method bidding (line 37) | public SniperSnapshot bidding(int newLastPrice, int newLastBid) {
    method winning (line 41) | public SniperSnapshot winning(int newLastPrice) {
    method losing (line 45) | public SniperSnapshot losing(int newLastPrice) {
    method closed (line 49) | public SniperSnapshot closed() {
    method failed (line 53) | public SniperSnapshot failed() {
    method isForSameItemAs (line 57) | public boolean isForSameItemAs(SniperSnapshot sniperSnapshot) {

FILE: src/auctionsniper/SniperState.java
  type SniperState (line 5) | public enum SniperState {
    method whenAuctionClosed (line 7) | @Override public SniperState whenAuctionClosed() { return LOST; }
    method whenAuctionClosed (line 10) | @Override public SniperState whenAuctionClosed() { return LOST; }
    method whenAuctionClosed (line 13) | @Override public SniperState whenAuctionClosed() { return WON; }
    method whenAuctionClosed (line 16) | @Override public SniperState whenAuctionClosed() { return LOST; }
    method whenAuctionClosed (line 22) | public SniperState whenAuctionClosed() {

FILE: src/auctionsniper/UserRequestListener.java
  type UserRequestListener (line 8) | public interface UserRequestListener extends EventListener {
    method joinAuction (line 9) | void joinAuction(Item item);
    class Item (line 11) | public static class Item {
      method Item (line 15) | public Item(String identifier, int stopPrice) {
      method allowsBid (line 20) | public boolean allowsBid(int bid) {
      method equals (line 24) | @Override
      method hashCode (line 26) | @Override
      method toString (line 28) | @Override

FILE: src/auctionsniper/ui/Column.java
  type Column (line 5) | public enum Column {
    method valueIn (line 7) | @Override public Object valueIn(SniperSnapshot snapshot) {
    method valueIn (line 12) | @Override public Object valueIn(SniperSnapshot snapshot) {
    method valueIn (line 17) | @Override public Object valueIn(SniperSnapshot snapshot) {
    method valueIn (line 22) | @Override public Object valueIn(SniperSnapshot snapshot) {
    method valueIn (line 27) | abstract public Object valueIn(SniperSnapshot snapshot);
    method Column (line 31) | private Column(String name) {
    method at (line 35) | public static Column at(int offset) { return values()[offset]; }

FILE: src/auctionsniper/ui/MainWindow.java
  class MainWindow (line 24) | public class MainWindow extends JFrame {
    method MainWindow (line 35) | public MainWindow(SniperPortfolio portfolio){
    method addUserRequestListener (line 44) | public void addUserRequestListener(UserRequestListener userRequestList...
    method fillContentPane (line 48) | private void fillContentPane(JTable snipersTable, JPanel controls) {
    method makeControls (line 55) | private JPanel makeControls() {
    method itemIdField (line 82) | private JTextField itemIdField() {
    method stopPriceField (line 89) | private JFormattedTextField stopPriceField() {
    method makeSnipersTable (line 96) | private JTable makeSnipersTable(SniperPortfolio portfolio) {

FILE: src/auctionsniper/ui/SnipersTableModel.java
  class SnipersTableModel (line 14) | public class SnipersTableModel extends AbstractTableModel implements Sni...
    method getColumnCount (line 20) | public int getColumnCount() {
    method getRowCount (line 24) | public int getRowCount() {
    method getColumnName (line 28) | @Override public String getColumnName(int column) {
    method getValueAt (line 32) | public Object getValueAt(int rowIndex, int columnIndex) {
    method textFor (line 36) | public static String textFor(SniperState state) {
    method sniperStateChanged (line 40) | public void sniperStateChanged(SniperSnapshot newSnapshot) {
    method sniperAdded (line 51) | public void sniperAdded(AuctionSniper sniper) {
    method addSniperSnapshot (line 56) | private void addSniperSnapshot(SniperSnapshot newSniper) {

FILE: src/auctionsniper/ui/SwingThreadSniperListener.java
  class SwingThreadSniperListener (line 11) | public class SwingThreadSniperListener implements SniperListener {
    method SwingThreadSniperListener (line 13) | public SwingThreadSniperListener(SniperListener delegate) {
    method sniperStateChanged (line 16) | public void sniperStateChanged(final SniperSnapshot snapshot) {

FILE: src/auctionsniper/util/Announcer.java
  class Announcer (line 11) | public class Announcer<T extends EventListener> {
    method Announcer (line 16) | public Announcer(Class<? extends T> listenerType) {
    method addListener (line 28) | public void addListener(T listener) {
    method removeListener (line 32) | public void removeListener(T listener) {
    method announce (line 36) | public T announce() {
    method announce (line 40) | private void announce(Method m, Object[] args) {
    method to (line 64) | public static <T extends EventListener> Announcer<T> to(Class<? extend...

FILE: src/auctionsniper/util/Defect.java
  class Defect (line 3) | public class Defect extends RuntimeException {
    method Defect (line 5) | public Defect() {
    method Defect (line 9) | public Defect(String message, Throwable cause) {
    method Defect (line 13) | public Defect(String message) {
    method Defect (line 17) | public Defect(Throwable cause) {

FILE: src/auctionsniper/xmpp/AuctionMessageTranslator.java
  class AuctionMessageTranslator (line 16) | public class AuctionMessageTranslator implements MessageListener {
    method AuctionMessageTranslator (line 21) | public AuctionMessageTranslator(String sniperId, AuctionEventListener ...
    method processMessage (line 27) | public void processMessage(Chat chat, Message message) {
    method translate (line 37) | private void translate(String messageBody) throws Exception {
    class AuctionEvent (line 49) | private static class AuctionEvent {
      method type (line 51) | public String type() throws MissingValueException { return get("Even...
      method currentPrice (line 52) | public int currentPrice() throws Exception { return getInt("CurrentP...
      method increment (line 53) | public int increment() throws Exception { return getInt("Increment"); }
      method isFrom (line 54) | public PriceSource isFrom(String sniperId) throws MissingValueExcept...
      method bidder (line 58) | private String bidder() throws MissingValueException { return get("B...
      method getInt (line 59) | private int getInt(String fieldName) throws Exception {
      method get (line 62) | private String get(String fieldName) throws MissingValueException {
      method addField (line 70) | private void addField(String field) {
      method from (line 75) | static AuctionEvent from(String messageBody) {
      method fieldsIn (line 83) | static String[] fieldsIn(String messageBody) {
    class MissingValueException (line 87) | private static class MissingValueException extends Exception {
      method MissingValueException (line 88) | public MissingValueException(String fieldName) {

FILE: src/auctionsniper/xmpp/LoggingXMPPFailureReporter.java
  class LoggingXMPPFailureReporter (line 5) | public class LoggingXMPPFailureReporter implements XMPPFailureReporter {
    method LoggingXMPPFailureReporter (line 9) | public LoggingXMPPFailureReporter(Logger logger) {
    method cannotTranslateMessage (line 13) | public void cannotTranslateMessage(String auctionId, String failedMess...

FILE: src/auctionsniper/xmpp/XMPPAuction.java
  class XMPPAuction (line 11) | public class XMPPAuction implements Auction {
    method XMPPAuction (line 19) | public XMPPAuction(XMPPConnection connection, String auctionJID, XMPPF...
    method bid (line 26) | public void bid(int amount) {
    method join (line 29) | public void join() {
    method addAuctionEventListener (line 33) | public void addAuctionEventListener(AuctionEventListener listener) {
    method translatorFor (line 37) | private AuctionMessageTranslator translatorFor(XMPPConnection connecti...
    method chatDisconnectorFor (line 41) | private AuctionEventListener
    method sendMessage (line 51) | private void sendMessage(final String message) {

FILE: src/auctionsniper/xmpp/XMPPAuctionException.java
  class XMPPAuctionException (line 3) | public class XMPPAuctionException extends Exception {
    method XMPPAuctionException (line 5) | public XMPPAuctionException(String message, Exception cause) {

FILE: src/auctionsniper/xmpp/XMPPAuctionHouse.java
  class XMPPAuctionHouse (line 15) | public class XMPPAuctionHouse implements AuctionHouse {
    method XMPPAuctionHouse (line 25) | public XMPPAuctionHouse(XMPPConnection connection) throws XMPPAuctionE...
    method auctionFor (line 30) | public Auction auctionFor(Item item) {
    method disconnect (line 34) | public void disconnect() {
    method connect (line 38) | public static XMPPAuctionHouse connect(String hostname, String usernam...
    method auctionId (line 49) | private static String auctionId(String itemId, XMPPConnection connecti...
    method makeLogger (line 53) | private Logger makeLogger() throws XMPPAuctionException {
    method simpleFileHandler (line 60) | private FileHandler simpleFileHandler() throws XMPPAuctionException {

FILE: src/auctionsniper/xmpp/XMPPFailureReporter.java
  type XMPPFailureReporter (line 3) | public interface XMPPFailureReporter {
    method cannotTranslateMessage (line 4) | void cannotTranslateMessage(String auctionId, String failedMessage, Ex...

FILE: test/end-to-end/test/endtoend/auctionsniper/ApplicationRunner.java
  class ApplicationRunner (line 15) | public class ApplicationRunner {
    method startBiddingIn (line 23) | public void startBiddingIn(final FakeAuctionServer... auctions) {
    method startBiddingWithStopPrice (line 29) | public void startBiddingWithStopPrice(FakeAuctionServer auction, int s...
    method hasShownSniperHasLostAuction (line 34) | public void hasShownSniperHasLostAuction(FakeAuctionServer auction, in...
    method hasShownSniperIsBidding (line 38) | public void hasShownSniperIsBidding(FakeAuctionServer auction, int las...
    method hasShownSniperIsWinning (line 42) | public void hasShownSniperIsWinning(FakeAuctionServer auction, int win...
    method hasShownSniperIsLosing (line 46) | public void hasShownSniperIsLosing(FakeAuctionServer auction, int last...
    method hasShownSniperHasWonAuction (line 50) | public void hasShownSniperHasWonAuction(FakeAuctionServer auction, int...
    method hasShownSniperHasFailed (line 54) | public void hasShownSniperHasFailed(FakeAuctionServer auction) {
    method reportsInvalidMessage (line 58) | public void reportsInvalidMessage(FakeAuctionServer auction, String br...
    method stop (line 62) | public void stop() {
    method startSniper (line 68) | private void startSniper() {
    method openBiddingFor (line 88) | private void openBiddingFor(FakeAuctionServer auction, int stopPrice) {
    method makeSureAwtIsLoadedBeforeStartingTheDriverOnOSXToStopDeadlock (line 94) | private void makeSureAwtIsLoadedBeforeStartingTheDriverOnOSXToStopDead...

FILE: test/end-to-end/test/endtoend/auctionsniper/AuctionLogDriver.java
  class AuctionLogDriver (line 14) | public class AuctionLogDriver {
    method hasEntry (line 17) | public void hasEntry(Matcher<String> matcher) throws IOException  {
    method clearLog (line 21) | public void clearLog() {

FILE: test/end-to-end/test/endtoend/auctionsniper/AuctionSniperDriver.java
  class AuctionSniperDriver (line 23) | @SuppressWarnings("unchecked")
    method AuctionSniperDriver (line 25) | public AuctionSniperDriver(int timeoutMillis) {
    method hasColumnTitles (line 33) | public void hasColumnTitles() {
    method showsSniperStatus (line 41) | public void showsSniperStatus(String itemId, int lastPrice, int lastBi...
    method startBiddingWithStopPrice (line 48) | public void startBiddingWithStopPrice(String itemId, int stopPrice) {
    method textField (line 54) | private JTextFieldDriver textField(String fieldName) {
    method bidButton (line 61) | private JButtonDriver bidButton() {

FILE: test/end-to-end/test/endtoend/auctionsniper/AuctionSniperEndToEndTest.java
  class AuctionSniperEndToEndTest (line 6) | public class AuctionSniperEndToEndTest {
    method sniperJoinsAuctionUntilAuctionCloses (line 12) | @Test public void
    method sniperMakesAHigherBidButLoses (line 22) | @Test public void
    method sniperWinsAnAuctionByBiddingHigher (line 37) | @Test public void
    method sniperBidsForMultipleItems (line 55) | @Test public void
    method sniperLosesAnAuctionWhenThePriceIsTooHigh (line 83) | @Test public void
    method sniperReportsInvalidAuctionMessageAndStopsRespondingToEvents (line 103) | @Test public void
    method waitForAnotherAuctionEvent (line 127) | private void waitForAnotherAuctionEvent() throws Exception {
    method stopAuction (line 133) | @After public void stopAuction() {
    method stopApplication (line 137) | @After public void stopApplication() {

FILE: test/end-to-end/test/endtoend/auctionsniper/FakeAuctionServer.java
  class FakeAuctionServer (line 22) | public class FakeAuctionServer {
    method FakeAuctionServer (line 34) | public FakeAuctionServer(String itemId) {
    method startSellingItem (line 39) | public void startSellingItem() throws XMPPException {
    method sendInvalidMessageContaining (line 51) | public void sendInvalidMessageContaining(String brokenMessage) throws ...
    method reportPrice (line 55) | public void reportPrice(int price, int increment, String bidder) throw...
    method hasReceivedJoinRequestFrom (line 62) | public void hasReceivedJoinRequestFrom(String sniperId) throws Interru...
    method hasReceivedBid (line 65) | public void hasReceivedBid(int bid, String sniperId) throws Interrupte...
    method receivesAMessageMatching (line 70) | private void receivesAMessageMatching(String sniperId, Matcher<? super...
    method announceClosed (line 75) | public void announceClosed() throws XMPPException {
    method stop (line 79) | public void stop() {
    method getItemId (line 83) | public String getItemId() {
    class SingleMessageListener (line 87) | public class SingleMessageListener implements MessageListener {
      method processMessage (line 90) | public void processMessage(Chat chat, Message message) {
      method receivesAMessage (line 93) | public void receivesAMessage() throws InterruptedException {
      method receivesAMessage (line 97) | public void receivesAMessage(Matcher<? super String> messageMatcher)

FILE: test/integration/test/integration/auctionsniper/ui/MainWindowTest.java
  class MainWindowTest (line 15) | public class MainWindowTest {
    method makesUserRequestWhenJoinButtonClicked (line 19) | @Test public void

FILE: test/integration/test/integration/auctionsniper/xmpp/XMPPAuctionHouseTest.java
  class XMPPAuctionHouseTest (line 21) | public class XMPPAuctionHouseTest {
    method openConnection (line 25) | @Before public void openConnection() throws XMPPAuctionException {
    method closeConnection (line 29) | @After public void closeConnection() {
    method startAuction (line 34) | @Before public void startAuction() throws XMPPException {
    method stopAuction (line 37) | @After public void stopAuction() {
    method receivesEventsFromAuctionServerAfterJoining (line 42) | @Test public void
    method auctionClosedListener (line 55) | private AuctionEventListener

FILE: test/unit/test/auctionsniper/AuctionSniperTest.java
  class AuctionSniperTest (line 31) | @RunWith(JMock.class)
    method attachListener (line 41) | @Before public void attachListener() {
    method hasInitialStateOfJoining (line 45) | @Test public void
    method reportsLostWhenAuctionClosesImmediately (line 50) | @Test public void
    method bidsHigherAndReportsBiddingWhenNewPriceArrives (line 59) | @Test public void
    method doesNotBidAndReportsLosingIfFirstPriceIsAboveStopPrice (line 74) | @Test public void
    method doesNotBidAndReportsLosingIfSubsequentPriceIsAboveStopPrice (line 86) | @Test public void
    method doesNotBidAndReportsLosingIfPriceAfterWinningIsAboveStopPrice (line 100) | @Test public void
    method continuesToBeLosingOnceStopPriceHasBeenReached (line 119) | @Test public void
    method reportsLostIfAuctionClosesWhenBidding (line 134) | @Test public void
    method reportsLostIfAuctionClosesWhenLosing (line 148) | @Test public void
    method reportsIsWinningWhenCurrentPriceComesFromSniper (line 162) | @Test public void
    method reportsWonIfAuctionClosesWhenWinning (line 174) | @Test public void
    method reportsFailedIfAuctionFailsWhenBidding (line 189) | @Test public void
    method reportsFailedIfAuctionFailsImmediately (line 200) | @Test public void
    method reportsFailedIfAuctionFailsWhenLosing (line 209) | @Test public void
    method reportsFailedIfAuctionFailsWhenWinning (line 220) | @Test public void
    method expectSniperToFailWhenItIs (line 234) | private void expectSniperToFailWhenItIs(final String state) {
    method ignoringAuction (line 241) | private void ignoringAuction() {
    method allowingSniperBidding (line 246) | private void allowingSniperBidding() {
    method allowingSniperLosing (line 250) | private void allowingSniperLosing() {
    method allowingSniperWinning (line 254) | private void allowingSniperWinning() {
    method allowSniperStateChange (line 258) | private void allowSniperStateChange(final SniperState newState, final ...
    method aSniperThatIs (line 264) | private Matcher<SniperSnapshot> aSniperThatIs(final SniperState state) {

FILE: test/unit/test/auctionsniper/SniperLauncherTest.java
  class SniperLauncherTest (line 21) | @RunWith(JMock.class)
    method addsNewSniperToCollectorAndThenJoinsAuction (line 30) | @Test public void
    method sniperForItem (line 46) | protected Matcher<AuctionSniper>sniperForItem(Item item) {

FILE: test/unit/test/auctionsniper/SniperPortfolioTest.java
  class SniperPortfolioTest (line 14) | @RunWith(JMock.class)
    method notifiesListenersOfNewSnipers (line 20) | @Test public void

FILE: test/unit/test/auctionsniper/SniperSnapshotTest.java
  class SniperSnapshotTest (line 12) | public class SniperSnapshotTest {
    method transitionsBetweenStates (line 14) | @Test public void
    method comparesItemIdentities (line 43) | @Test public void

FILE: test/unit/test/auctionsniper/SniperStateTests.java
  class SniperStateTests (line 10) | public class SniperStateTests {
    method isWonWhenAuctionClosesWhileWinning (line 12) | @Test public void
    method defectIfAuctionClosesWhenWon (line 19) | @Test(expected=Defect.class) public void
    method defectIfAuctionClosesWhenLost (line 24) | @Test(expected=Defect.class) public void

FILE: test/unit/test/auctionsniper/ui/ColumnTest.java
  class ColumnTest (line 11) | public class ColumnTest {
    method retrievesValuesFromASniperSnapshot (line 13) | @Test public void

FILE: test/unit/test/auctionsniper/ui/SnipersTableModelTest.java
  class SnipersTableModelTest (line 28) | @RunWith(JMock.class)
    method attachModelListener (line 36) | @Before public void attachModelListener() {
    method hasEnoughColumns (line 40) | @Test public void
    method setsUpColumnHeadings (line 45) | @Test public void
    method acceptsNewSniper (line 52) | @Test public void
    method setsSniperValuesInColumns (line 63) | @Test public void
    method notifiesListenersWhenAddingASniper (line 78) | @Test public void
    method holdsSnipersInAdditionOrder (line 92) | @Test public void
    method updatesCorrectRowForSniper (line 106) | @Test public void
    method throwsDefectIfNoExistingSniperForAnUpdate (line 124) | @Test(expected=Defect.class) public void
    method assertRowMatchesSnapshot (line 129) | private void assertRowMatchesSnapshot(int row, SniperSnapshot snapshot) {
    method cellValue (line 136) | private Object cellValue(int rowIndex, Column column) {
    method anyInsertionEvent (line 140) | Matcher<TableModelEvent> anyInsertionEvent() {
    method anInsertionAtRow (line 143) | Matcher<TableModelEvent> anInsertionAtRow(final int row) {
    method aChangeInRow (line 147) | private Matcher<TableModelEvent> aChangeInRow(int row) {

FILE: test/unit/test/auctionsniper/xmpp/AuctionMessageTranslatorTest.java
  class AuctionMessageTranslatorTest (line 16) | @RunWith(JMock.class)
    method notifiesAuctionClosedWhenCloseMessageReceived (line 26) | @Test public void
    method notifiesBidDetailsWhenCurrentPriceMessageReceivedFromOtherBidder (line 38) | @Test public void
    method notifiesBidDetailsWhenCurrentPriceMessageReceivedFromSniper (line 50) | @Test public void
    method notifiesAuctionFailedWhenBadMessageReceived (line 63) | @Test public void
    method notifiesAuctionFailedWhenEventTypeMissing (line 71) | @Test public void
    method message (line 79) | private Message message(String body) {
    method expectFailureWithMessage (line 85) | private void expectFailureWithMessage(final String badMessage) {

FILE: test/unit/test/auctionsniper/xmpp/LoggingXMPPFailureReporterTest.java
  class LoggingXMPPFailureReporterTest (line 16) | @RunWith(JMock.class)
    method resetLogging (line 24) | @AfterClass public static void resetLogging() {
    method writesMessageTranslationFailureToLog (line 27) | @Test public void
Condensed preview — 64 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (80K chars).
[
  {
    "path": ".classpath",
    "chars": 1587,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"src\" path=\"src\"/>\n\t<classpathentry kind=\"src\" "
  },
  {
    "path": ".project",
    "chars": 377,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>auction-example-06</name>\n\t<comment></comment>\n\t<proj"
  },
  {
    "path": "build.xml",
    "chars": 2552,
    "preview": "<project name=\"Auction Sniper\" default=\"build\">\n    <property name=\"build.dir\" location=\"build\" />\n    <property name=\"s"
  },
  {
    "path": "license.txt",
    "chars": 619,
    "preview": "This project is Copyright 2009 Stephen Freeman and Nathaniel Pryce\n\n   Licensed under the Apache License, Version 2.0 (t"
  },
  {
    "path": "src/auctionsniper/Auction.java",
    "chars": 156,
    "preview": "package auctionsniper;\n\npublic interface Auction {\n\n  void join();\n  void bid(int amount);\n  void addAuctionEventListene"
  },
  {
    "path": "src/auctionsniper/AuctionEventListener.java",
    "chars": 303,
    "preview": "package auctionsniper;\n\nimport java.util.EventListener;\n\npublic interface AuctionEventListener extends EventListener {\n "
  },
  {
    "path": "src/auctionsniper/AuctionHouse.java",
    "chars": 140,
    "preview": "package auctionsniper;\n\nimport auctionsniper.UserRequestListener.Item;\n\npublic interface AuctionHouse {\n  Auction auctio"
  },
  {
    "path": "src/auctionsniper/AuctionSniper.java",
    "chars": 1442,
    "preview": "package auctionsniper;\n\nimport auctionsniper.UserRequestListener.Item;\nimport auctionsniper.util.Announcer;\n\npublic clas"
  },
  {
    "path": "src/auctionsniper/Main.java",
    "chars": 1443,
    "preview": "package auctionsniper;\n\nimport java.awt.event.WindowAdapter;\nimport java.awt.event.WindowEvent;\n\nimport javax.swing.Swin"
  },
  {
    "path": "src/auctionsniper/SniperCollector.java",
    "chars": 101,
    "preview": "package auctionsniper;\n\npublic interface SniperCollector {\n  void addSniper(AuctionSniper sniper);\n}\n"
  },
  {
    "path": "src/auctionsniper/SniperLauncher.java",
    "chars": 589,
    "preview": "package auctionsniper;\n\n\npublic class SniperLauncher implements UserRequestListener {\n  private final AuctionHouse aucti"
  },
  {
    "path": "src/auctionsniper/SniperListener.java",
    "chars": 167,
    "preview": "package auctionsniper;\n\nimport java.util.EventListener;\n\npublic interface SniperListener extends EventListener { \n  void"
  },
  {
    "path": "src/auctionsniper/SniperPortfolio.java",
    "chars": 706,
    "preview": "package auctionsniper;\n\nimport java.util.ArrayList;\nimport java.util.EventListener;\n\nimport auctionsniper.util.Announcer"
  },
  {
    "path": "src/auctionsniper/SniperSnapshot.java",
    "chars": 1771,
    "preview": "package auctionsniper;\n\nimport org.apache.commons.lang.builder.EqualsBuilder;\nimport org.apache.commons.lang.builder.Has"
  },
  {
    "path": "src/auctionsniper/SniperState.java",
    "chars": 569,
    "preview": "package auctionsniper;\n\nimport auctionsniper.util.Defect;\n\npublic enum SniperState { \n  JOINING {\n    @Override public S"
  },
  {
    "path": "src/auctionsniper/UserRequestListener.java",
    "chars": 885,
    "preview": "package auctionsniper;\n\nimport java.util.EventListener;\n\nimport org.apache.commons.lang.builder.EqualsBuilder;\nimport or"
  },
  {
    "path": "src/auctionsniper/ui/Column.java",
    "chars": 896,
    "preview": "package auctionsniper.ui;\n\nimport auctionsniper.SniperSnapshot;\n\npublic enum Column { \n  ITEM_IDENTIFIER(\"Item\") { \n    "
  },
  {
    "path": "src/auctionsniper/ui/MainWindow.java",
    "chars": 3480,
    "preview": "package auctionsniper.ui;\n\nimport java.awt.BorderLayout;\nimport java.awt.Container;\nimport java.awt.FlowLayout;\nimport j"
  },
  {
    "path": "src/auctionsniper/ui/SnipersTableModel.java",
    "chars": 1821,
    "preview": "package auctionsniper.ui;\n\nimport java.util.ArrayList;\n\nimport javax.swing.table.AbstractTableModel;\n\nimport auctionsnip"
  },
  {
    "path": "src/auctionsniper/ui/SwingThreadSniperListener.java",
    "chars": 568,
    "preview": "/**\n * \n */\npackage auctionsniper.ui;\n\nimport javax.swing.SwingUtilities;\n\nimport auctionsniper.SniperListener;\nimport a"
  },
  {
    "path": "src/auctionsniper/util/Announcer.java",
    "chars": 1673,
    "preview": "package auctionsniper.util;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.InvocationTargetExcept"
  },
  {
    "path": "src/auctionsniper/util/Defect.java",
    "chars": 317,
    "preview": "package auctionsniper.util;\n\npublic class Defect extends RuntimeException {\n\n  public Defect() {\n    super();\n  }\n\n  pub"
  },
  {
    "path": "src/auctionsniper/xmpp/AuctionMessageTranslator.java",
    "chars": 3200,
    "preview": "package auctionsniper.xmpp;\n\nimport static auctionsniper.AuctionEventListener.PriceSource.FromOtherBidder;\nimport static"
  },
  {
    "path": "src/auctionsniper/xmpp/LoggingXMPPFailureReporter.java",
    "chars": 563,
    "preview": "package auctionsniper.xmpp;\n\nimport java.util.logging.Logger;\n\npublic class LoggingXMPPFailureReporter implements XMPPFa"
  },
  {
    "path": "src/auctionsniper/xmpp/XMPPAuction.java",
    "chars": 2104,
    "preview": "package auctionsniper.xmpp;\n\nimport org.jivesoftware.smack.Chat;\nimport org.jivesoftware.smack.XMPPConnection;\nimport or"
  },
  {
    "path": "src/auctionsniper/xmpp/XMPPAuctionException.java",
    "chars": 183,
    "preview": "package auctionsniper.xmpp;\n\npublic class XMPPAuctionException extends Exception {\n\n  public XMPPAuctionException(String"
  },
  {
    "path": "src/auctionsniper/xmpp/XMPPAuctionHouse.java",
    "chars": 2617,
    "preview": "package auctionsniper.xmpp;\n\nimport java.util.logging.FileHandler;\nimport java.util.logging.Logger;\nimport java.util.log"
  },
  {
    "path": "src/auctionsniper/xmpp/XMPPFailureReporter.java",
    "chars": 162,
    "preview": "package auctionsniper.xmpp;\n\npublic interface XMPPFailureReporter { \n  void cannotTranslateMessage(String auctionId, Str"
  },
  {
    "path": "test/end-to-end/test/endtoend/auctionsniper/ApplicationRunner.java",
    "chars": 3558,
    "preview": "package test.endtoend.auctionsniper;\n\nimport static auctionsniper.ui.SnipersTableModel.textFor;\nimport static org.hamcre"
  },
  {
    "path": "test/end-to-end/test/endtoend/auctionsniper/AuctionLogDriver.java",
    "chars": 630,
    "preview": "package test.endtoend.auctionsniper;\n\nimport static org.junit.Assert.assertThat;\n\nimport java.io.File;\nimport java.io.IO"
  },
  {
    "path": "test/end-to-end/test/endtoend/auctionsniper/AuctionSniperDriver.java",
    "chars": 2499,
    "preview": "package test.endtoend.auctionsniper;\n\nimport static auctionsniper.ui.MainWindow.NEW_ITEM_ID_NAME;\nimport static auctions"
  },
  {
    "path": "test/end-to-end/test/endtoend/auctionsniper/AuctionSniperEndToEndTest.java",
    "chars": 5037,
    "preview": "package test.endtoend.auctionsniper;\n\nimport org.junit.After;\nimport org.junit.Test;\n\npublic class AuctionSniperEndToEnd"
  },
  {
    "path": "test/end-to-end/test/endtoend/auctionsniper/FakeAuctionServer.java",
    "chars": 3766,
    "preview": "package test.endtoend.auctionsniper;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.h"
  },
  {
    "path": "test/integration/test/integration/auctionsniper/ui/MainWindowTest.java",
    "chars": 1111,
    "preview": "package test.integration.auctionsniper.ui;\n\nimport static org.hamcrest.Matchers.equalTo;\n\nimport org.junit.Test;\n\nimport"
  },
  {
    "path": "test/integration/test/integration/auctionsniper/xmpp/XMPPAuctionHouseTest.java",
    "chars": 2217,
    "preview": "package test.integration.auctionsniper.xmpp;\n\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.jun"
  },
  {
    "path": "test/unit/test/auctionsniper/AuctionSniperTest.java",
    "chars": 8949,
    "preview": "package test.auctionsniper;\n\nimport static auctionsniper.SniperState.BIDDING;\nimport static auctionsniper.SniperState.LO"
  },
  {
    "path": "test/unit/test/auctionsniper/SniperLauncherTest.java",
    "chars": 1956,
    "preview": "package test.auctionsniper;\n\nimport static org.hamcrest.Matchers.equalTo;\n\nimport org.hamcrest.FeatureMatcher;\nimport or"
  },
  {
    "path": "test/unit/test/auctionsniper/SniperPortfolioTest.java",
    "chars": 949,
    "preview": "package test.auctionsniper;\n\nimport org.jmock.Expectations;\nimport org.jmock.Mockery;\nimport org.jmock.integration.junit"
  },
  {
    "path": "test/unit/test/auctionsniper/SniperSnapshotTest.java",
    "chars": 1484,
    "preview": "package test.auctionsniper;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nim"
  },
  {
    "path": "test/unit/test/auctionsniper/SniperStateTests.java",
    "chars": 751,
    "preview": "package test.auctionsniper;\n\nimport static org.junit.Assert.assertEquals;\n\nimport org.junit.Test;\n\nimport auctionsniper."
  },
  {
    "path": "test/unit/test/auctionsniper/ui/ColumnTest.java",
    "chars": 641,
    "preview": "package test.auctionsniper.ui;\n\nimport static org.junit.Assert.assertEquals;\n\nimport org.junit.Test;\n\nimport auctionsnip"
  },
  {
    "path": "test/unit/test/auctionsniper/ui/SnipersTableModelTest.java",
    "chars": 4827,
    "preview": "package test.auctionsniper.ui;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.hasProp"
  },
  {
    "path": "test/unit/test/auctionsniper/xmpp/AuctionMessageTranslatorTest.java",
    "chars": 3266,
    "preview": "package test.auctionsniper.xmpp;\n\nimport org.jivesoftware.smack.Chat;\nimport org.jivesoftware.smack.packet.Message;\nimpo"
  },
  {
    "path": "test/unit/test/auctionsniper/xmpp/LoggingXMPPFailureReporterTest.java",
    "chars": 1275,
    "preview": "package test.auctionsniper.xmpp;\n\nimport java.util.logging.LogManager;\nimport java.util.logging.Logger;\n\nimport org.jmoc"
  },
  {
    "path": "tools/openfire-version-is-3.6.txt",
    "chars": 0,
    "preview": ""
  }
]

// ... and 19 more files (download for full content)

About this extraction

This page contains the full source code of the sf105/goos-code GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 64 files (72.2 KB), approximately 19.5k tokens, and a symbol index with 265 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!