Skip to content
Browse files

Added new DataBlockFactory and javadoc

  • Loading branch information...
1 parent 650dcc6 commit 250d5fc30ab17f76dc1ef59f21bef8180b1355de Briggs committed
View
13 src/main/java/com/acidblue/collections/binpack/BadBlock.java
@@ -1,7 +1,16 @@
package com.acidblue.collections.binpack;
-public interface BadBlock {
+/**
+ * Simply adds a new {@link #getMessage()} to a block for returning a human, or machine,
+ * readable reason that the block could not be added.
+ */
+public interface BadBlock<E> extends Block<E> {
- //todo, is a string good enough?
+
+ /**
+ * Returns a message for the reason the block could not be used.
+ *
+ * @return A string
+ */
public abstract String getMessage();
}
View
19 src/main/java/com/acidblue/collections/binpack/BadDataBlock.java
@@ -1,14 +1,31 @@
package com.acidblue.collections.binpack;
-public class BadDataBlock<E> extends DataBlock<E> implements BadBlock {
+/**
+ * A block which encapsulates data which could not be used by a {@link BinPacker} instance.
+ * Clients inspect the {@link #getMessage()} to determine the reason.
+ * @param <E>
+ */
+public class BadDataBlock<E> extends DataBlock<E> implements BadBlock<E> {
private String message;
+ /**
+ * Creates a new block with the data to be encapsulated and a mandatory
+ * message as to why it could not be added.
+ * @param data The data, which failed packing, to encapsulate
+ * @param message The reason the block could not be packed
+ */
public BadDataBlock(final E data, final String message) {
super(data);
this.setMessage(message);
}
+ /**
+ * Returns a reason, either human or machine readable, why the encapsulated data could not packed by the
+ * bin packer.
+ *
+ * @return Some string message
+ */
public String getMessage() {
return message;
}
View
6 src/main/java/com/acidblue/collections/binpack/BinEvent.java
@@ -2,6 +2,12 @@
import java.util.EventObject;
+/**
+ * Represents an event during the bin packing process.
+ *
+ * @param <T>
+ * @see BinEventListener
+ */
public class BinEvent<T extends Block<?>> extends EventObject {
private final T block;
View
21 src/main/java/com/acidblue/collections/binpack/BinEventListener.java
@@ -2,11 +2,32 @@
import java.util.EventListener;
+/**
+ Describes the callbacks that an instance of a {@link BinPacker} can invoke on its listeners.
+ Clients can inspect the {@link BinEvent} to determine the data and the bins associated with the
+ event.
+ */
public interface BinEventListener extends EventListener {
+ /**
+ * A new bin was created.
+ *
+ * @param event The event
+ */
public abstract void binCreated(BinEvent event);
+ /**
+ * An item added to a bin.
+ *
+ * @param event The event
+ */
public abstract void itemAdded(BinEvent event);
+ /**
+ * An item was ignored during the process. Clients can inspect the event's
+ * {@link com.acidblue.collections.binpack.BinEvent#getBlock()} value to determine why it was ignored.
+ *
+ * @param event The event
+ */
public abstract void itemIgnored(BinEvent event);
}
View
35 src/main/java/com/acidblue/collections/binpack/BinPacker.java
@@ -2,17 +2,52 @@
import java.util.List;
+/**
+ * Describes the operations needed for a a Bin Packing API.
+ * @param <T>
+ */
public interface BinPacker<T extends Block<?>> {
+ /**
+ * The number of bins currently in use by the bin packer.
+ *
+ * @return A non-negative value
+ */
public abstract long getSize();
+ /**
+ * Adds the given block to the bin packer.
+ *
+ * @param block A block (non-null)
+ * @return A reference to the Bin which the block was added
+ */
public abstract Bin<T> add(T block);
+ /**
+ * Adds all the given items to the bin packer.
+ *
+ * @param list A list of items (non-null)
+ */
public abstract void addAll(List<T> list);
+ /**
+ * Returns all the bins (with their associated blocks) in the bin packer.
+ *
+ * @return A non-null value
+ */
public abstract List<Bin<T>> getBins();
+ /**
+ * Adds an event listener to the bin packer.
+ *
+ * @param listener A listener (non-null)
+ */
public abstract void addBinEventListener(BinEventListener listener);
+ /**
+ * Removes an event listener from the bin packer.
+ *
+ * @param listener A listener (non-null)
+ */
public abstract void removeBinEventListener(BinEventListener listener);
}
View
18 src/main/java/com/acidblue/collections/binpack/Block.java
@@ -1,8 +1,26 @@
package com.acidblue.collections.binpack;
+/**
+ * A block is a simple abstraction of something that can be measured as a long value. A block
+ * has two simple methods. First is {@link #getSize()}, which returns the size (whatever this means
+ * in the context that is being used) and {@link #getData()} which returns the actual thing which was
+ * measured.
+ *
+ * @param <T> The type for which the block represents.
+ */
public interface Block<T> {
+ /**
+ * Returns the size of the block.
+ *
+ * @return A non-negative value.
+ */
public abstract long getSize();
+ /**
+ * Returns actual data represented by the Block.
+ *
+ * @return The data of the block
+ */
public abstract T getData();
}
View
7 src/main/java/com/acidblue/collections/binpack/DataBlock.java
@@ -1,5 +1,10 @@
package com.acidblue.collections.binpack;
+/**
+ * Simply begins the definition of a {@link Block} by encapsulating the data accociated with the block.
+ * Sublcasses need to implement the {@link #getSize()} method.
+ * @param <E>
+ */
public abstract class DataBlock<E> implements Block<E> {
private final E data;
@@ -8,8 +13,6 @@ public DataBlock(final E data) {
this.data = data;
}
- public abstract long getSize();
-
public String toString() {
final StringBuilder builder = new StringBuilder("DataBlock[");
View
58 src/main/java/com/acidblue/collections/binpack/DataBlockFactory.java
@@ -0,0 +1,58 @@
+package com.acidblue.collections.binpack;
+
+/**
+ * A factory which returns encapsulated data items within a block. A client simply invokes the
+ * {@link #dataBlock(Object, com.acidblue.collections.binpack.DataBlockFactory.LengthCalc)}
+ * while providing the factor an instance of a {@link LengthCalc}.
+ *
+ * @author Briggs
+ * @since 2.0
+ */
+public class DataBlockFactory {
+
+ private DataBlockFactory(){
+ //Singleton
+ }
+
+
+ /**
+ * Defines a single method ({@link #getLength(Object)} which returns the length of the Object provided.
+ *
+ * @param <E> The type of data encapsulated within the block.
+ */
+ public static interface LengthCalc<E> {
+ public long getLength(E item);
+ }
+
+ /**
+ * Returns a data block ({@link DataBlock}.
+ *
+ * @param data The data encapsulated within the block
+ * @param calc The calculation for determining the length of the block
+ * @param <E> The type encapsulated within the block
+ * @return A newly created data block
+ */
+ public static <E> DataBlock<E> dataBlock(final E data, final LengthCalc<E> calc) {
+ return new InternalDataBlock<E>(data, calc);
+ }
+
+ private static class InternalDataBlock<E> extends DataBlock<E> {
+ private final LengthCalc<E> calc;
+
+ public InternalDataBlock(final E data, final LengthCalc<E> calc) {
+ super(data);
+ if (calc == null) {
+ throw new NullPointerException("calc was null");
+ }
+
+ this.calc = calc;
+ }
+
+ @Override
+ public long getSize() {
+ return calc.getLength(this.getData());
+ }
+ }
+
+
+}
View
16 src/main/java/com/acidblue/collections/binpack/FirstFitBinPacker.java
@@ -5,6 +5,11 @@
import java.util.Comparator;
import java.util.List;
+/**
+ * A BinPacker which will simply fit a block within the first available bin. No optimization is done.
+ *
+ * @param <T> The type encapsulated within the bins of the bin packer
+ */
public class FirstFitBinPacker<T extends Block<?>> extends AbstractBinPacker<T> {
private final Comparator<T> BLOCK_COMPARATOR = new Comparator<T>() {
@@ -14,6 +19,12 @@ public int compare(final T firstBlock, final T secondBlock) {
}
};
+ /**
+ * Creates a bin packer with the maximum length a bit can be. All blocks are accumulated within
+ * each bin and when that threshold is reached, a new bin will be created.
+ *
+ * @param maxBinSize The max length of a bin
+ */
public FirstFitBinPacker(long maxBinSize) {
super(maxBinSize);
}
@@ -22,7 +33,10 @@ private void sort(List<T> blocks) {
Collections.sort(blocks, BLOCK_COMPARATOR);
}
- public Bin<T> add(T item) {
+ public Bin<T> add(final T item) {
+
+ //todo, rewrite this. This was code from a class I lost the source for and had to decompile it.
+ //this got really funky.
if (item == null) {
throw new NullPointerException("item cannot be null");
}
View
4 src/main/java/com/acidblue/collections/binpack/VetoableBlockBinPacker.java
@@ -51,8 +51,8 @@ public List getPackedBlocks() {
throw new NullPointerException("item was null");
}
- //todo fix this, fix this ugly code
-
+ //todo, rewrite this. This was code from a class I lost the source for and had to decompile it.
+ //this got really funky.
Bin<T> targetBin = null;
boolean added = false;
int i = 0;
View
41 src/main/test/com/acidblue/collections/binpack/Main.java
@@ -4,6 +4,8 @@
import java.util.List;
import java.util.Random;
+import com.acidblue.collections.binpack.DataBlockFactory.LengthCalc;
+
/**
* One crappy test class. No junit at the moment.
*
@@ -12,44 +14,35 @@
*/
public class Main {
- private static class StringBlock implements Block<String> {
-
- private String data;
-
- public StringBlock(final String str) {
- this.data = str;
- }
-
- public String getData() {
- return data;
- }
-
- public long getSize() {
- return data.length();
- }
- }
public static void main(String[] args) {
final RandomStringGenerator[] random = {new RandomStringGenerator(3), new RandomStringGenerator(20),new RandomStringGenerator(30)};
-
- final List<StringBlock> blocks = new ArrayList<StringBlock>();
+
+ //java sucks for this. Why can't we have first class functions?
+ final LengthCalc<String> calc = new LengthCalc<String>() {
+ @Override
+ public long getLength(final String item) {
+ return item.length();
+ }
+ };
+
+
+ final List<Block<String>> blocks = new ArrayList<Block<String>>();
for (int i = 0; i < 400; i++) {
final int ran = (int) (Math.random() * 3);
final String randomString = random[ran].nextString();
- blocks.add(new StringBlock(randomString));
+ blocks.add(DataBlockFactory.dataBlock(randomString, calc));
}
//add one long string that can't be added.
-
final String ignoreMe = "This is an annoyingly long string that will no fit in any bins, so" +
" we should have an ignored block";
- blocks.add(new StringBlock("This is an annoyingly long string that will no fit in any bins, so" +
- " we should have an ignored block"));
+ blocks.add(DataBlockFactory.dataBlock(ignoreMe, calc));
- VetoableBlockBinPacker<StringBlock> packer = new VetoableBlockBinPacker<StringBlock>(blocks, 60, 10);
+ VetoableBlockBinPacker<Block<String>> packer = new VetoableBlockBinPacker<Block<String>>(blocks, 60, 10);
packer.addBinEventListener(new BinEventListener() {
public void binCreated(final BinEvent event) {
@@ -70,7 +63,7 @@ public void itemIgnored(final BinEvent event) {
}
});
- List<Bin<StringBlock>> bins = packer.packBlocks().getBins();
+ List<Bin<Block<String>>> bins = packer.packBlocks().getBins();
System.out.println(bins.size());

0 comments on commit 250d5fc

Please sign in to comment.
Something went wrong with that request. Please try again.