Index: trunk/src/org/openstreetmap/josm/gui/io/IUploadDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/IUploadDialog.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/gui/io/IUploadDialog.java	(revision 12687)
@@ -3,4 +3,6 @@
 
 import java.util.Map;
+
+import org.openstreetmap.josm.io.UploadStrategySpecification;
 
 /**
Index: trunk/src/org/openstreetmap/josm/gui/io/MaxChangesetSizeExceededPolicy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/MaxChangesetSizeExceededPolicy.java	(revision 12686)
+++ 	(revision )
@@ -1,24 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.io;
-
-/**
- * This determines what to do when the max changeset size was exceeded by a upload.
- */
-public enum MaxChangesetSizeExceededPolicy {
-    /**
-     * Abort uploading. Send the user back to map editing.
-     */
-    ABORT,
-    /**
-     * Fill one changeset. If it is full send the user back to the
-     * upload dialog where he can choose another changeset or another
-     * upload strategy if he or she wants to.
-     */
-    FILL_ONE_CHANGESET_AND_RETURN_TO_UPLOAD_DIALOG,
-
-    /**
-     * Automatically open as many new changesets as necessary to upload
-     * the data.
-     */
-    AUTOMATICALLY_OPEN_NEW_CHANGESETS
-}
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java	(revision 12687)
@@ -57,4 +57,6 @@
 import org.openstreetmap.josm.gui.util.WindowGeometry;
 import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.io.UploadStrategy;
+import org.openstreetmap.josm.io.UploadStrategySpecification;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageOverlay;
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadLayerTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadLayerTask.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadLayerTask.java	(revision 12687)
@@ -23,4 +23,5 @@
 import org.openstreetmap.josm.io.OsmServerWriter;
 import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.io.UploadStrategySpecification;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Logging;
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java	(revision 12687)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.io.Capabilities;
 import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.io.UploadStrategySpecification;
 import org.openstreetmap.josm.tools.ImageProvider;
 
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 12687)
@@ -31,4 +31,5 @@
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.io.ChangesetClosedException;
+import org.openstreetmap.josm.io.MaxChangesetSizeExceededPolicy;
 import org.openstreetmap.josm.io.MessageNotifier;
 import org.openstreetmap.josm.io.OsmApi;
@@ -37,4 +38,5 @@
 import org.openstreetmap.josm.io.OsmTransferCanceledException;
 import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.io.UploadStrategySpecification;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadStrategy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadStrategy.java	(revision 12686)
+++ 	(revision )
@@ -1,113 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.io;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.util.Locale;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.tools.Logging;
-
-/**
- * The chunk mode to use when uploading
- */
-public enum UploadStrategy {
-    /**
-     * Uploads the objects individually, one request per object
-     */
-    INDIVIDUAL_OBJECTS_STRATEGY("individualobjects"),
-    /**
-     * Upload the objects in junks of n objects using m diff uploads
-     */
-    CHUNKED_DATASET_STRATEGY("chunked"),
-    /**
-     * Upload the objects in one request using 1 diff upload
-     */
-    SINGLE_REQUEST_STRATEGY("singlerequest");
-
-    private final String preferenceValue;
-
-    UploadStrategy(String preferenceValue) {
-        this.preferenceValue = preferenceValue;
-    }
-
-    /**
-     * Reads the value from preferences
-     * @param preferenceValue The preference value
-     * @return The {@link UploadStrategy} for that preference or <code>null</code> if unknown
-     */
-    public static UploadStrategy fromPreference(String preferenceValue) {
-        if (preferenceValue == null) return null;
-        preferenceValue = preferenceValue.trim().toLowerCase(Locale.ENGLISH);
-        for (UploadStrategy strategy: values()) {
-            if (strategy.getPreferenceValue().equals(preferenceValue))
-                return strategy;
-        }
-        return null;
-    }
-
-    /**
-     * Replies the value which is written to the preferences for a specific
-     * upload strategy
-     *
-     * @return the value which is written to the preferences for a specific
-     * upload strategy
-     */
-    public String getPreferenceValue() {
-        return preferenceValue;
-    }
-
-    /**
-     * the default upload strategy
-     */
-    public static final UploadStrategy DEFAULT_UPLOAD_STRATEGY = SINGLE_REQUEST_STRATEGY;
-
-    /**
-     * Replies the upload strategy currently configured in the preferences.
-     *
-     * First checks for the preference key <pre>osm-server.upload-strategy</pre>. If not
-     * present, checks for the legacy preference key <pre>osm-server.atomic-upload</pre>.
-     *
-     * If both are missing or if the preference value is illegal, {@link #DEFAULT_UPLOAD_STRATEGY}
-     * is replied.
-     *
-     * @return the upload strategy currently configured in the preferences.
-     */
-    public static UploadStrategy getFromPreferences() {
-        String v = Main.pref.get("osm-server.upload-strategy", null);
-        if (v == null) {
-            // legacy support. Until 12/2009 we had osm-server.atomic-upload only.
-            // If we still find "osm-server.atomic-upload" we use it and remove it.
-            // When the preferences are saved the next time, "osm-server.upload-strategy"
-            // will be inserted.
-            v = Main.pref.get("osm-server.atomic-upload", null);
-            if (v != null) {
-                Main.pref.removeFromCollection("osm-server.atomic-upload", v);
-            } else {
-                v = "";
-            }
-            v = v.trim().toLowerCase(Locale.ENGLISH);
-            if ("true".equals(v))
-                return SINGLE_REQUEST_STRATEGY;
-            else if ("false".equals(v))
-                return INDIVIDUAL_OBJECTS_STRATEGY;
-            else
-                return DEFAULT_UPLOAD_STRATEGY;
-        }
-        UploadStrategy strategy = fromPreference(v);
-        if (strategy == null) {
-            Logging.warn(tr("Unexpected value for key ''{0}'' in preferences, got ''{1}''", "osm-server.upload-strategy", v));
-            return DEFAULT_UPLOAD_STRATEGY;
-        }
-        return strategy;
-    }
-
-    /**
-     * Saves the upload strategy <code>strategy</code> to the preferences.
-     *
-     * @param strategy the strategy to save
-     */
-    public static void saveToPreferences(UploadStrategy strategy) {
-        Main.pref.put("osm-server.upload-strategy", strategy.getPreferenceValue());
-    }
-}
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java	(revision 12687)
@@ -35,5 +35,8 @@
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.io.Capabilities;
+import org.openstreetmap.josm.io.MaxChangesetSizeExceededPolicy;
 import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.io.UploadStrategy;
+import org.openstreetmap.josm.io.UploadStrategySpecification;
 import org.openstreetmap.josm.tools.Logging;
 
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySpecification.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySpecification.java	(revision 12686)
+++ 	(revision )
@@ -1,168 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.io;
-
-import java.util.Objects;
-
-/**
- * An UploadStrategySpecification consists of the parameter describing the strategy
- * for uploading a collection of {@link org.openstreetmap.josm.data.osm.OsmPrimitive}.
- *
- * This includes:
- * <ul>
- * <li>a decision on which {@link UploadStrategy} to use</li>
- * <li>the upload chunk size</li>
- * <li>whether to close the changeset used after the upload</li>
- * </ul>
- */
-public class UploadStrategySpecification {
-    /** indicates that the chunk size isn't specified */
-    public static final int UNSPECIFIED_CHUNK_SIZE = -1;
-
-    private UploadStrategy strategy;
-    private int chunkSize;
-    private MaxChangesetSizeExceededPolicy policy;
-    private boolean closeChangesetAfterUpload;
-
-    /**
-     * Creates a new upload strategy with default values.
-     */
-    public UploadStrategySpecification() {
-        this.strategy = UploadStrategy.DEFAULT_UPLOAD_STRATEGY;
-        this.chunkSize = UNSPECIFIED_CHUNK_SIZE;
-        this.policy = null;
-        this.closeChangesetAfterUpload = true;
-    }
-
-    /**
-     * Clones another upload strategy. If other is null, assumes default values.
-     *
-     * @param other the other upload strategy
-     */
-    public UploadStrategySpecification(UploadStrategySpecification other) {
-        if (other != null) {
-            this.strategy = other.strategy;
-            this.chunkSize = other.chunkSize;
-            this.policy = other.policy;
-            this.closeChangesetAfterUpload = other.closeChangesetAfterUpload;
-        }
-    }
-
-    /**
-     * Replies the upload strategy
-     * @return the upload strategy
-     */
-    public UploadStrategy getStrategy() {
-        return strategy;
-    }
-
-    /**
-     * Gets the chunk size
-     * @return The max size of each upload chunk
-     */
-    public int getChunkSize() {
-        return chunkSize;
-    }
-
-    /**
-     * Gets a special value that is used to indicate that the chunk size was not specified
-     * @return A special integer
-     */
-    public static int getUnspecifiedChunkSize() {
-        return UNSPECIFIED_CHUNK_SIZE;
-    }
-
-    /**
-     * Gets the policy that is used when the server max changeset size is exceeded.
-     * @return What to do when the changeset size is exceeded
-     */
-    public MaxChangesetSizeExceededPolicy getPolicy() {
-        return policy;
-    }
-
-    /**
-     * Sets the upload strategy (chunk mode)
-     * @param strategy The upload strategy
-     * @return This object, for easy chaining
-     */
-    public UploadStrategySpecification setStrategy(UploadStrategy strategy) {
-        this.strategy = strategy;
-        return this;
-    }
-
-    /**
-     * Sets the upload chunk size
-     * @param chunkSize The chunk size
-     * @return This object, for easy chaining
-     */
-    public UploadStrategySpecification setChunkSize(int chunkSize) {
-        this.chunkSize = chunkSize;
-        return this;
-    }
-
-    /**
-     * Sets the policy to use when the max changeset size is exceeded
-     * @param policy The policy
-     * @return This object, for easy chaining
-     */
-    public UploadStrategySpecification setPolicy(MaxChangesetSizeExceededPolicy policy) {
-        this.policy = policy;
-        return this;
-    }
-
-    /**
-     * Sets whether to close the changeset after this upload
-     * @param closeChangesetAfterUpload <code>true</code> to close it
-     * @return This object, for easy chaining
-     */
-    public UploadStrategySpecification setCloseChangesetAfterUpload(boolean closeChangesetAfterUpload) {
-        this.closeChangesetAfterUpload = closeChangesetAfterUpload;
-        return this;
-    }
-
-    /**
-     * Gets if the changeset should be closed after this upload
-     * @return <code>true</code> to close it
-     */
-    public boolean isCloseChangesetAfterUpload() {
-        return closeChangesetAfterUpload;
-    }
-
-    /**
-     * Gets the number of requests that will be required to upload the objects
-     * @param numObjects The number of objects
-     * @return The number of requests
-     */
-    public int getNumRequests(int numObjects) {
-        if (numObjects <= 0)
-            return 0;
-        switch(strategy) {
-        case INDIVIDUAL_OBJECTS_STRATEGY: return numObjects;
-        case SINGLE_REQUEST_STRATEGY: return 1;
-        case CHUNKED_DATASET_STRATEGY:
-            if (chunkSize == UNSPECIFIED_CHUNK_SIZE)
-                return 0;
-            else
-                return (int) Math.ceil((double) numObjects / (double) chunkSize);
-        }
-        // should not happen
-        return 0;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(strategy, chunkSize, policy, closeChangesetAfterUpload);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null || getClass() != obj.getClass())
-            return false;
-        UploadStrategySpecification that = (UploadStrategySpecification) obj;
-        return chunkSize == that.chunkSize &&
-                closeChangesetAfterUpload == that.closeChangesetAfterUpload &&
-                strategy == that.strategy &&
-                policy == that.policy;
-    }
-}
Index: trunk/src/org/openstreetmap/josm/io/MaxChangesetSizeExceededPolicy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/MaxChangesetSizeExceededPolicy.java	(revision 12687)
+++ trunk/src/org/openstreetmap/josm/io/MaxChangesetSizeExceededPolicy.java	(revision 12687)
@@ -0,0 +1,25 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+/**
+ * This determines what to do when the max changeset size was exceeded by a upload.
+ * @since 12687 (moved from {@code gui.io} package)
+ */
+public enum MaxChangesetSizeExceededPolicy {
+    /**
+     * Abort uploading. Send the user back to map editing.
+     */
+    ABORT,
+    /**
+     * Fill one changeset. If it is full send the user back to the
+     * upload dialog where he can choose another changeset or another
+     * upload strategy if he or she wants to.
+     */
+    FILL_ONE_CHANGESET_AND_RETURN_TO_UPLOAD_DIALOG,
+
+    /**
+     * Automatically open as many new changesets as necessary to upload
+     * the data.
+     */
+    AUTOMATICALLY_OPEN_NEW_CHANGESETS
+}
Index: trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 12686)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 12687)
@@ -17,5 +17,4 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.gui.JosmUserIdentityManager;
-import org.openstreetmap.josm.gui.io.UploadStrategySpecification;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
Index: trunk/src/org/openstreetmap/josm/io/UploadStrategy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/UploadStrategy.java	(revision 12687)
+++ trunk/src/org/openstreetmap/josm/io/UploadStrategy.java	(revision 12687)
@@ -0,0 +1,114 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.Locale;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * The chunk mode to use when uploading
+ * @since 12687 (moved from {@code gui.io} package)
+ */
+public enum UploadStrategy {
+    /**
+     * Uploads the objects individually, one request per object
+     */
+    INDIVIDUAL_OBJECTS_STRATEGY("individualobjects"),
+    /**
+     * Upload the objects in junks of n objects using m diff uploads
+     */
+    CHUNKED_DATASET_STRATEGY("chunked"),
+    /**
+     * Upload the objects in one request using 1 diff upload
+     */
+    SINGLE_REQUEST_STRATEGY("singlerequest");
+
+    private final String preferenceValue;
+
+    UploadStrategy(String preferenceValue) {
+        this.preferenceValue = preferenceValue;
+    }
+
+    /**
+     * Reads the value from preferences
+     * @param preferenceValue The preference value
+     * @return The {@link UploadStrategy} for that preference or <code>null</code> if unknown
+     */
+    public static UploadStrategy fromPreference(String preferenceValue) {
+        if (preferenceValue == null) return null;
+        preferenceValue = preferenceValue.trim().toLowerCase(Locale.ENGLISH);
+        for (UploadStrategy strategy: values()) {
+            if (strategy.getPreferenceValue().equals(preferenceValue))
+                return strategy;
+        }
+        return null;
+    }
+
+    /**
+     * Replies the value which is written to the preferences for a specific
+     * upload strategy
+     *
+     * @return the value which is written to the preferences for a specific
+     * upload strategy
+     */
+    public String getPreferenceValue() {
+        return preferenceValue;
+    }
+
+    /**
+     * the default upload strategy
+     */
+    public static final UploadStrategy DEFAULT_UPLOAD_STRATEGY = SINGLE_REQUEST_STRATEGY;
+
+    /**
+     * Replies the upload strategy currently configured in the preferences.
+     *
+     * First checks for the preference key <pre>osm-server.upload-strategy</pre>. If not
+     * present, checks for the legacy preference key <pre>osm-server.atomic-upload</pre>.
+     *
+     * If both are missing or if the preference value is illegal, {@link #DEFAULT_UPLOAD_STRATEGY}
+     * is replied.
+     *
+     * @return the upload strategy currently configured in the preferences.
+     */
+    public static UploadStrategy getFromPreferences() {
+        String v = Main.pref.get("osm-server.upload-strategy", null);
+        if (v == null) {
+            // legacy support. Until 12/2009 we had osm-server.atomic-upload only.
+            // If we still find "osm-server.atomic-upload" we use it and remove it.
+            // When the preferences are saved the next time, "osm-server.upload-strategy"
+            // will be inserted.
+            v = Main.pref.get("osm-server.atomic-upload", null);
+            if (v != null) {
+                Main.pref.removeFromCollection("osm-server.atomic-upload", v);
+            } else {
+                v = "";
+            }
+            v = v.trim().toLowerCase(Locale.ENGLISH);
+            if ("true".equals(v))
+                return SINGLE_REQUEST_STRATEGY;
+            else if ("false".equals(v))
+                return INDIVIDUAL_OBJECTS_STRATEGY;
+            else
+                return DEFAULT_UPLOAD_STRATEGY;
+        }
+        UploadStrategy strategy = fromPreference(v);
+        if (strategy == null) {
+            Logging.warn(tr("Unexpected value for key ''{0}'' in preferences, got ''{1}''", "osm-server.upload-strategy", v));
+            return DEFAULT_UPLOAD_STRATEGY;
+        }
+        return strategy;
+    }
+
+    /**
+     * Saves the upload strategy <code>strategy</code> to the preferences.
+     *
+     * @param strategy the strategy to save
+     */
+    public static void saveToPreferences(UploadStrategy strategy) {
+        Main.pref.put("osm-server.upload-strategy", strategy.getPreferenceValue());
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/UploadStrategySpecification.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/UploadStrategySpecification.java	(revision 12687)
+++ trunk/src/org/openstreetmap/josm/io/UploadStrategySpecification.java	(revision 12687)
@@ -0,0 +1,169 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import java.util.Objects;
+
+/**
+ * An UploadStrategySpecification consists of the parameter describing the strategy
+ * for uploading a collection of {@link org.openstreetmap.josm.data.osm.OsmPrimitive}.
+ *
+ * This includes:
+ * <ul>
+ * <li>a decision on which {@link UploadStrategy} to use</li>
+ * <li>the upload chunk size</li>
+ * <li>whether to close the changeset used after the upload</li>
+ * </ul>
+ * @since 12687 (moved from {@code gui.io} package)
+ */
+public class UploadStrategySpecification {
+    /** indicates that the chunk size isn't specified */
+    public static final int UNSPECIFIED_CHUNK_SIZE = -1;
+
+    private UploadStrategy strategy;
+    private int chunkSize;
+    private MaxChangesetSizeExceededPolicy policy;
+    private boolean closeChangesetAfterUpload;
+
+    /**
+     * Creates a new upload strategy with default values.
+     */
+    public UploadStrategySpecification() {
+        this.strategy = UploadStrategy.DEFAULT_UPLOAD_STRATEGY;
+        this.chunkSize = UNSPECIFIED_CHUNK_SIZE;
+        this.policy = null;
+        this.closeChangesetAfterUpload = true;
+    }
+
+    /**
+     * Clones another upload strategy. If other is null, assumes default values.
+     *
+     * @param other the other upload strategy
+     */
+    public UploadStrategySpecification(UploadStrategySpecification other) {
+        if (other != null) {
+            this.strategy = other.strategy;
+            this.chunkSize = other.chunkSize;
+            this.policy = other.policy;
+            this.closeChangesetAfterUpload = other.closeChangesetAfterUpload;
+        }
+    }
+
+    /**
+     * Replies the upload strategy
+     * @return the upload strategy
+     */
+    public UploadStrategy getStrategy() {
+        return strategy;
+    }
+
+    /**
+     * Gets the chunk size
+     * @return The max size of each upload chunk
+     */
+    public int getChunkSize() {
+        return chunkSize;
+    }
+
+    /**
+     * Gets a special value that is used to indicate that the chunk size was not specified
+     * @return A special integer
+     */
+    public static int getUnspecifiedChunkSize() {
+        return UNSPECIFIED_CHUNK_SIZE;
+    }
+
+    /**
+     * Gets the policy that is used when the server max changeset size is exceeded.
+     * @return What to do when the changeset size is exceeded
+     */
+    public MaxChangesetSizeExceededPolicy getPolicy() {
+        return policy;
+    }
+
+    /**
+     * Sets the upload strategy (chunk mode)
+     * @param strategy The upload strategy
+     * @return This object, for easy chaining
+     */
+    public UploadStrategySpecification setStrategy(UploadStrategy strategy) {
+        this.strategy = strategy;
+        return this;
+    }
+
+    /**
+     * Sets the upload chunk size
+     * @param chunkSize The chunk size
+     * @return This object, for easy chaining
+     */
+    public UploadStrategySpecification setChunkSize(int chunkSize) {
+        this.chunkSize = chunkSize;
+        return this;
+    }
+
+    /**
+     * Sets the policy to use when the max changeset size is exceeded
+     * @param policy The policy
+     * @return This object, for easy chaining
+     */
+    public UploadStrategySpecification setPolicy(MaxChangesetSizeExceededPolicy policy) {
+        this.policy = policy;
+        return this;
+    }
+
+    /**
+     * Sets whether to close the changeset after this upload
+     * @param closeChangesetAfterUpload <code>true</code> to close it
+     * @return This object, for easy chaining
+     */
+    public UploadStrategySpecification setCloseChangesetAfterUpload(boolean closeChangesetAfterUpload) {
+        this.closeChangesetAfterUpload = closeChangesetAfterUpload;
+        return this;
+    }
+
+    /**
+     * Gets if the changeset should be closed after this upload
+     * @return <code>true</code> to close it
+     */
+    public boolean isCloseChangesetAfterUpload() {
+        return closeChangesetAfterUpload;
+    }
+
+    /**
+     * Gets the number of requests that will be required to upload the objects
+     * @param numObjects The number of objects
+     * @return The number of requests
+     */
+    public int getNumRequests(int numObjects) {
+        if (numObjects <= 0)
+            return 0;
+        switch(strategy) {
+        case INDIVIDUAL_OBJECTS_STRATEGY: return numObjects;
+        case SINGLE_REQUEST_STRATEGY: return 1;
+        case CHUNKED_DATASET_STRATEGY:
+            if (chunkSize == UNSPECIFIED_CHUNK_SIZE)
+                return 0;
+            else
+                return (int) Math.ceil((double) numObjects / (double) chunkSize);
+        }
+        // should not happen
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(strategy, chunkSize, policy, closeChangesetAfterUpload);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        UploadStrategySpecification that = (UploadStrategySpecification) obj;
+        return chunkSize == that.chunkSize &&
+                closeChangesetAfterUpload == that.closeChangesetAfterUpload &&
+                strategy == that.strategy &&
+                policy == that.policy;
+    }
+}
