diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryCollectionListModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryCollectionListModel.java
new file mode 100755
index 000000000..5027b1b37
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryCollectionListModel.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.ui.category;
+
+import com.arsdigita.bebop.list.ListModel;
+import org.libreccm.categorization.Category;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A {@link ListModel} that iterates over categories via a cursor.
+ *
+ * @author Yannick Bülter
+ */
+public final class CategoryCollectionListModel implements ListModel {
+
+ private Category m_cat;
+ private long m_excludedID;
+ private Iterator iterator;
+
+
+ /**
+ * Constructs a new CategoryCollectionListModel
+ */
+ public CategoryCollectionListModel(Collection coll) {
+ this(coll, -1); //Hopefully a decent replacement for null in BigDecimal. Negative ids would be weird...
+ }
+
+ /**
+ * Constructs a new CategoryCollectionListModel
+ */
+ public CategoryCollectionListModel(Collection coll,
+ long excludedID) {
+
+ m_excludedID = excludedID;
+ m_cat = null;
+ iterator = coll.iterator();
+ }
+
+ public boolean next() {
+ if (iterator.hasNext()) {
+ final Category category = iterator.next();
+ if (Long.parseLong(category.getUniqueId()) == m_excludedID) {
+ return next();
+ } else {
+ m_cat = category;
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private Category getCategory() {
+ if ( m_cat == null ) {
+ throw new IllegalStateException("call next() first");
+ }
+ return m_cat;
+ }
+
+ /**
+ * Reads the name of the category.
+ *
+ * Quasimodo:
+ * Modified to ensure that the value is read from Category (and not the
+ * localized version). This is necessary because we are in the admin GUI,
+ * a localized version would be confusing.
+ */
+ public Object getElement() {
+ return getCategory().getName();
+ }
+
+ public String getKey() {
+ return getCategory().getUniqueId();
+ }
+}