]> source.dussan.org Git - gitblit.git/commitdiff
fix formatting (use tab for identation)
authorMartin Spielmann <mail@martinspielmann.de>
Mon, 6 Nov 2017 13:11:55 +0000 (14:11 +0100)
committerMartin Spielmann <mail@martinspielmann.de>
Mon, 6 Nov 2017 13:21:25 +0000 (14:21 +0100)
src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java

index 4b16c20150d505c4645340cec4e63b88970b8957..1bf3efec90b6dbf2919f6065e62a74eaa58fe1ad 100644 (file)
@@ -59,431 +59,442 @@ import com.gitblit.wicket.pages.UserPage;
 \r
 public class RepositoriesPanel extends BasePanel {\r
 \r
-    private static final long serialVersionUID = 1L;\r
-\r
-    private enum CollapsibleRepositorySetting {\r
-        DISABLED,\r
-\r
-        EXPANDED,\r
-\r
-        COLLAPSED;\r
-\r
-        public static CollapsibleRepositorySetting get(String name) {\r
-            CollapsibleRepositorySetting returnVal = CollapsibleRepositorySetting.DISABLED;\r
-            for (CollapsibleRepositorySetting setting : values()) {\r
-                if (setting.name().equalsIgnoreCase(name)) {\r
-                    returnVal = setting;\r
-                    break;\r
-                }\r
-            }\r
-            return returnVal;\r
-        }\r
-    }\r
-\r
-    public RepositoriesPanel(String wicketId, final boolean showAdmin, final boolean showManagement, List<RepositoryModel> models, boolean enableLinks,\r
-            final Map<AccessRestrictionType, String> accessRestrictionTranslations) {\r
-        super(wicketId);\r
-\r
-        final boolean linksActive = enableLinks;\r
-        final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true);\r
-        final String collapsibleRespositorySetting = app().settings().getString(Keys.web.collapsibleRepositoryGroups, null);\r
-        final CollapsibleRepositorySetting collapsibleRepoGroups = CollapsibleRepositorySetting.get(collapsibleRespositorySetting);\r
-\r
-        final UserModel user = GitBlitWebSession.get().getUser();\r
-\r
-        IDataProvider<RepositoryModel> dp = null;\r
-\r
-        Fragment managementLinks;\r
-        if (showAdmin) {\r
-            // user is admin\r
-            managementLinks = new Fragment("managementPanel", "adminLinks", this);\r
-            managementLinks.add(new Link<Void>("clearCache") {\r
-\r
-                private static final long serialVersionUID = 1L;\r
-\r
-                @Override\r
-                public void onClick() {\r
-                    app().repositories().resetRepositoryListCache();\r
-                    setResponsePage(RepositoriesPage.class);\r
-                }\r
-            }.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true)));\r
-            managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));\r
-            add(managementLinks);\r
-        } else if (showManagement && user != null && user.canCreate()) {\r
-            // user can create personal repositories\r
-            managementLinks = new Fragment("managementPanel", "personalLinks", this);\r
-            managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));\r
-            add(managementLinks);\r
-        } else {\r
-            // user has no management permissions\r
-            add(new Label("managementPanel").setVisible(false));\r
-        }\r
-\r
-        if (app().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("tree")) {\r
-            TreeNodeModel tree = new TreeNodeModel();\r
-            for (RepositoryModel model : models) {\r
-                String rootPath = StringUtils.getRootPath(model.name);\r
-                if (StringUtils.isEmpty(rootPath)) {\r
-                    tree.add(model);\r
-                } else {\r
-                    // create folder structure\r
-                    tree.add(rootPath, model);\r
-                }\r
-            }\r
-\r
-            WebMarkupContainer container = new WebMarkupContainer("row");\r
-            add(container);\r
-            container.add(new NestedRepositoryTreePanel("rowContent", Model.of(tree), accessRestrictionTranslations, enableLinks));\r
-\r
-            Fragment fragment = new Fragment("headerContent", "groupRepositoryHeader", this);\r
-            Fragment allCollapsible = new Fragment("allCollapsible", "tableAllCollapsible", this);\r
-            fragment.add(allCollapsible);\r
-            add(fragment);\r
-\r
-        } else if (app().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {\r
-            List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();\r
-            Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();\r
-            for (RepositoryModel model : models) {\r
-                String rootPath = StringUtils.getRootPath(model.name);\r
-                if (StringUtils.isEmpty(rootPath)) {\r
-                    // root repository\r
-                    rootRepositories.add(model);\r
-                } else {\r
-                    // non-root, grouped repository\r
-                    if (!groups.containsKey(rootPath)) {\r
-                        groups.put(rootPath, new ArrayList<RepositoryModel>());\r
-                    }\r
-                    groups.get(rootPath).add(model);\r
-                }\r
-            }\r
-            List<String> roots = new ArrayList<String>(groups.keySet());\r
-            Collections.sort(roots);\r
-\r
-            if (rootRepositories.size() > 0) {\r
-                // inject the root repositories at the top of the page\r
-                roots.add(0, "");\r
-                groups.put("", rootRepositories);\r
-            }\r
-\r
-            List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();\r
-            for (String root : roots) {\r
-                List<RepositoryModel> subModels = groups.get(root);\r
-                ProjectModel project = app().projects().getProjectModel(root);\r
-                GroupRepositoryModel group = new GroupRepositoryModel(project == null ? root : project.name, subModels.size());\r
-                if (project != null) {\r
-                    group.title = project.title;\r
-                    group.description = project.description;\r
-                }\r
-                groupedModels.add(group);\r
-                Collections.sort(subModels);\r
-                groupedModels.addAll(subModels);\r
-            }\r
-            dp = new ListDataProvider<RepositoryModel>(groupedModels);\r
-        } else {\r
-            dp = new SortableRepositoriesProvider(models);\r
-        }\r
-\r
-        if (dp != null) {\r
-            final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);\r
-\r
-            DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {\r
-                private static final long serialVersionUID = 1L;\r
-                int counter;\r
-                String currGroupName;\r
-\r
-                @Override\r
-                protected void onBeforeRender() {\r
-                    super.onBeforeRender();\r
-                    counter = 0;\r
-                }\r
-\r
-                @Override\r
-                public void populateItem(final Item<RepositoryModel> item) {\r
-                    final RepositoryModel entry = item.getModelObject();\r
-                    if (entry instanceof GroupRepositoryModel) {\r
-                        GroupRepositoryModel groupRow = (GroupRepositoryModel) entry;\r
-                        currGroupName = entry.name;\r
-                        Fragment row = new Fragment("rowContent", "groupRepositoryRow", this);\r
-                        if (collapsibleRepoGroups == CollapsibleRepositorySetting.EXPANDED) {\r
-                            Fragment groupCollapsible = new Fragment("groupCollapsible", "tableGroupMinusCollapsible", this);\r
-                            row.add(groupCollapsible);\r
-                        } else if (collapsibleRepoGroups == CollapsibleRepositorySetting.COLLAPSED) {\r
-                            Fragment groupCollapsible = new Fragment("groupCollapsible", "tableGroupPlusCollapsible", this);\r
-                            row.add(groupCollapsible);\r
-                        } else {\r
-                            Fragment groupCollapsible = new Fragment("groupCollapsible", "emptyFragment", this);\r
-                            row.add(groupCollapsible);\r
-                        }\r
-                        item.add(row);\r
-\r
-                        String name = groupRow.name;\r
-                        if (name.startsWith(ModelUtils.getUserRepoPrefix())) {\r
-                            // user page\r
-                            String username = ModelUtils.getUserNameFromRepoPath(name);\r
-                            UserModel user = app().users().getUserModel(username);\r
-                            row.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()) + " (" + groupRow.count + ")", UserPage.class,\r
-                                    WicketUtils.newUsernameParameter(username)));\r
-                            row.add(new Label("groupDescription", getString("gb.personalRepositories")));\r
-                        } else {\r
-                            // project page\r
-                            row.add(new LinkPanel("groupName", null, groupRow.toString(), ProjectPage.class, WicketUtils.newProjectParameter(entry.name)));\r
-                            row.add(new Label("groupDescription", entry.description == null ? "" : entry.description));\r
-                        }\r
-                        WicketUtils.setCssClass(item, "group collapsible");\r
-                        // reset counter so that first row is light background\r
-                        counter = 0;\r
-                        return;\r
-                    }\r
-                    Fragment row = new Fragment("rowContent", "repositoryRow", this);\r
-                    item.add(row);\r
-\r
-                    // show colored repository type icon\r
-                    Fragment iconFragment;\r
-                    if (entry.isMirror) {\r
-                        iconFragment = new Fragment("repoIcon", "mirrorIconFragment", this);\r
-                    } else if (entry.isFork()) {\r
-                        iconFragment = new Fragment("repoIcon", "forkIconFragment", this);\r
-                    } else if (entry.isBare) {\r
-                        iconFragment = new Fragment("repoIcon", "repoIconFragment", this);\r
-                    } else {\r
-                        iconFragment = new Fragment("repoIcon", "cloneIconFragment", this);\r
-                    }\r
-                    if (showSwatch) {\r
-                        WicketUtils.setCssStyle(iconFragment, "color:" + StringUtils.getColor(entry.toString()));\r
-                    }\r
-                    row.add(iconFragment);\r
-\r
-                    // try to strip group name for less cluttered list\r
-                    String repoName = entry.toString();\r
-                    if (!StringUtils.isEmpty(currGroupName) && (repoName.indexOf('/') > -1)) {\r
-                        repoName = repoName.substring(currGroupName.length() + 1);\r
-                    }\r
-\r
-                    if (linksActive) {\r
-                        Class<? extends BasePage> linkPage = SummaryPage.class;\r
-                        PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);\r
-                        row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));\r
-                        row.add(new LinkPanel("repositoryDescription", "list", entry.description, linkPage, pp));\r
-                    } else {\r
-                        // no links like on a federation page\r
-                        row.add(new Label("repositoryName", repoName));\r
-                        row.add(new Label("repositoryDescription", entry.description));\r
-                    }\r
-                    if (entry.hasCommits) {\r
-                        // Existing repository\r
-                        row.add(new Label("repositorySize", entry.size).setVisible(showSize));\r
-                    } else {\r
-                        // New repository\r
-                        row.add(new Label("repositorySize", "<span class='empty'>(" + getString("gb.empty") + ")</span>").setEscapeModelStrings(false));\r
-                    }\r
-\r
-                    if (entry.isSparkleshared()) {\r
-                        row.add(WicketUtils.newImage("sparkleshareIcon", "star_16x16.png", getString("gb.isSparkleshared")));\r
-                    } else {\r
-                        row.add(WicketUtils.newClearPixel("sparkleshareIcon").setVisible(false));\r
-                    }\r
-\r
-                    if (!entry.isMirror && entry.isFrozen) {\r
-                        row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", getString("gb.isFrozen")));\r
-                    } else {\r
-                        row.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false));\r
-                    }\r
-\r
-                    if (entry.isFederated) {\r
-                        row.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png", getString("gb.isFederated")));\r
-                    } else {\r
-                        row.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false));\r
-                    }\r
-\r
-                    if (entry.isMirror) {\r
-                        row.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png", getString("gb.isMirror")));\r
-                    } else {\r
-                        switch (entry.accessRestriction) {\r
-                        case NONE:\r
-                            row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));\r
-                            break;\r
-                        case PUSH:\r
-                            row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));\r
-                            break;\r
-                        case CLONE:\r
-                            row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));\r
-                            break;\r
-                        case VIEW:\r
-                            row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));\r
-                            break;\r
-                        default:\r
-                            row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));\r
-                        }\r
-                    }\r
-\r
-                    String owner = "";\r
-                    if (!ArrayUtils.isEmpty(entry.owners)) {\r
-                        // display first owner\r
-                        for (String username : entry.owners) {\r
-                            UserModel ownerModel = app().users().getUserModel(username);\r
-                            if (ownerModel != null) {\r
-                                owner = ownerModel.getDisplayName();\r
-                                break;\r
-                            }\r
-                        }\r
-                        if (entry.owners.size() > 1) {\r
-                            owner += ", ...";\r
-                        }\r
-                    }\r
-                    Label ownerLabel = new Label("repositoryOwner", owner);\r
-                    WicketUtils.setHtmlTooltip(ownerLabel, ArrayUtils.toString(entry.owners));\r
-                    row.add(ownerLabel);\r
-\r
-                    String lastChange;\r
-                    if (entry.lastChange.getTime() == 0) {\r
-                        lastChange = "--";\r
-                    } else {\r
-                        lastChange = getTimeUtils().timeAgo(entry.lastChange);\r
-                    }\r
-                    Label lastChangeLabel = new Label("repositoryLastChange", lastChange);\r
-                    row.add(lastChangeLabel);\r
-                    WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange));\r
-                    if (!StringUtils.isEmpty(entry.lastChangeAuthor)) {\r
-                        WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor);\r
-                    }\r
-\r
-                    WicketUtils.setAlternatingBackground(item, counter);\r
-                    counter++;\r
-                }\r
-            };\r
-            add(dataView);\r
-\r
-            if (dp instanceof SortableDataProvider<?>) {\r
-                // add sortable header\r
-                SortableDataProvider<?> sdp = (SortableDataProvider<?>) dp;\r
-                Fragment fragment = new Fragment("headerContent", "flatRepositoryHeader", this);\r
-                fragment.add(newSort("orderByRepository", SortBy.repository, sdp, dataView));\r
-                fragment.add(newSort("orderByDescription", SortBy.description, sdp, dataView));\r
-                fragment.add(newSort("orderByOwner", SortBy.owner, sdp, dataView));\r
-                fragment.add(newSort("orderByDate", SortBy.date, sdp, dataView));\r
-                add(fragment);\r
-            } else {\r
-                // not sortable\r
-                Fragment fragment = new Fragment("headerContent", "groupRepositoryHeader", this);\r
-                if (collapsibleRepoGroups == CollapsibleRepositorySetting.EXPANDED || collapsibleRepoGroups == CollapsibleRepositorySetting.COLLAPSED) {\r
-                    Fragment allCollapsible = new Fragment("allCollapsible", "tableAllCollapsible", this);\r
-                    fragment.add(allCollapsible);\r
-                } else {\r
-                    Fragment allCollapsible = new Fragment("allCollapsible", "emptyFragment", this);\r
-                    fragment.add(allCollapsible);\r
-                }\r
-                add(fragment);\r
-            }\r
-        }\r
-    }\r
-\r
-    private static class GroupRepositoryModel extends RepositoryModel {\r
-\r
-        private static final long serialVersionUID = 1L;\r
-\r
-        int count;\r
-        String title;\r
-\r
-        GroupRepositoryModel(String name, int count) {\r
-            super(name, "", "", new Date(0));\r
-            this.count = count;\r
-        }\r
-\r
-        @Override\r
-        public String toString() {\r
-            return (StringUtils.isEmpty(title) ? name : title) + " (" + count + ")";\r
-        }\r
-    }\r
-\r
-    protected enum SortBy {\r
-        repository, description, owner, date;\r
-    }\r
-\r
-    protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp, final DataView<?> dataView) {\r
-        return new OrderByBorder(wicketId, field.name(), dp) {\r
-            private static final long serialVersionUID = 1L;\r
-\r
-            @Override\r
-            protected void onSortChanged() {\r
-                dataView.setCurrentPage(0);\r
-            }\r
-        };\r
-    }\r
-\r
-    private static class SortableRepositoriesProvider extends SortableDataProvider<RepositoryModel> {\r
-\r
-        private static final long serialVersionUID = 1L;\r
-\r
-        private List<RepositoryModel> list;\r
-\r
-        protected SortableRepositoriesProvider(List<RepositoryModel> list) {\r
-            this.list = list;\r
-            setSort(SortBy.date.name(), false);\r
-        }\r
-\r
-        @Override\r
-        public int size() {\r
-            if (list == null) {\r
-                return 0;\r
-            }\r
-            return list.size();\r
-        }\r
-\r
-        @Override\r
-        public IModel<RepositoryModel> model(RepositoryModel header) {\r
-            return new Model<RepositoryModel>(header);\r
-        }\r
-\r
-        @Override\r
-        public Iterator<RepositoryModel> iterator(int first, int count) {\r
-            SortParam sp = getSort();\r
-            String prop = sp.getProperty();\r
-            final boolean asc = sp.isAscending();\r
-\r
-            if (prop == null || prop.equals(SortBy.date.name())) {\r
-                Collections.sort(list, new Comparator<RepositoryModel>() {\r
-                    @Override\r
-                    public int compare(RepositoryModel o1, RepositoryModel o2) {\r
-                        if (asc) {\r
-                            return o1.lastChange.compareTo(o2.lastChange);\r
-                        }\r
-                        return o2.lastChange.compareTo(o1.lastChange);\r
-                    }\r
-                });\r
-            } else if (prop.equals(SortBy.repository.name())) {\r
-                Collections.sort(list, new Comparator<RepositoryModel>() {\r
-                    @Override\r
-                    public int compare(RepositoryModel o1, RepositoryModel o2) {\r
-                        if (asc) {\r
-                            return o1.name.compareTo(o2.name);\r
-                        }\r
-                        return o2.name.compareTo(o1.name);\r
-                    }\r
-                });\r
-            } else if (prop.equals(SortBy.owner.name())) {\r
-                Collections.sort(list, new Comparator<RepositoryModel>() {\r
-                    @Override\r
-                    public int compare(RepositoryModel o1, RepositoryModel o2) {\r
-                        String own1 = ArrayUtils.toString(o1.owners);\r
-                        String own2 = ArrayUtils.toString(o2.owners);\r
-                        if (asc) {\r
-                            return own1.compareTo(own2);\r
-                        }\r
-                        return own2.compareTo(own1);\r
-                    }\r
-                });\r
-            } else if (prop.equals(SortBy.description.name())) {\r
-                Collections.sort(list, new Comparator<RepositoryModel>() {\r
-                    @Override\r
-                    public int compare(RepositoryModel o1, RepositoryModel o2) {\r
-                        if (asc) {\r
-                            return o1.description.compareTo(o2.description);\r
-                        }\r
-                        return o2.description.compareTo(o1.description);\r
-                    }\r
-                });\r
-            }\r
-            return list.subList(first, first + count).iterator();\r
-        }\r
-    }\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private enum CollapsibleRepositorySetting {\r
+               DISABLED,\r
+\r
+               EXPANDED,\r
+\r
+               COLLAPSED;\r
+\r
+               public static CollapsibleRepositorySetting get(String name) {\r
+                       CollapsibleRepositorySetting returnVal = CollapsibleRepositorySetting.DISABLED;\r
+                       for (CollapsibleRepositorySetting setting : values()) {\r
+                               if (setting.name().equalsIgnoreCase(name)) {\r
+                                       returnVal = setting;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       return returnVal;\r
+               }\r
+       }\r
+\r
+       public RepositoriesPanel(String wicketId, final boolean showAdmin, final boolean showManagement,\r
+                       List<RepositoryModel> models, boolean enableLinks,\r
+                       final Map<AccessRestrictionType, String> accessRestrictionTranslations) {\r
+               super(wicketId);\r
+\r
+               final boolean linksActive = enableLinks;\r
+               final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true);\r
+               final String collapsibleRespositorySetting = app().settings().getString(Keys.web.collapsibleRepositoryGroups, null);\r
+               final CollapsibleRepositorySetting collapsibleRepoGroups = CollapsibleRepositorySetting.get(collapsibleRespositorySetting);\r
+\r
+               final UserModel user = GitBlitWebSession.get().getUser();\r
+\r
+               IDataProvider<RepositoryModel> dp = null;\r
+\r
+               Fragment managementLinks;\r
+               if (showAdmin) {\r
+                       // user is admin\r
+                       managementLinks = new Fragment("managementPanel", "adminLinks", this);\r
+                       managementLinks.add(new Link<Void>("clearCache") {\r
+\r
+                               private static final long serialVersionUID = 1L;\r
+\r
+                               @Override\r
+                               public void onClick() {\r
+                                       app().repositories().resetRepositoryListCache();\r
+                                       setResponsePage(RepositoriesPage.class);\r
+                               }\r
+                       }.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true)));\r
+                       managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));\r
+                       add(managementLinks);\r
+               } else if (showManagement && user != null && user.canCreate()) {\r
+                       // user can create personal repositories\r
+                       managementLinks = new Fragment("managementPanel", "personalLinks", this);\r
+                       managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));\r
+                       add(managementLinks);\r
+               } else {\r
+                       // user has no management permissions\r
+                       add (new Label("managementPanel").setVisible(false));\r
+               }\r
+\r
+               if (app().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("tree")) {\r
+                       TreeNodeModel tree = new TreeNodeModel();\r
+                       for (RepositoryModel model : models) {\r
+                               String rootPath = StringUtils.getRootPath(model.name);\r
+                               if (StringUtils.isEmpty(rootPath)) {\r
+                                       tree.add(model);\r
+                               } else {\r
+                                       // create folder structure\r
+                                       tree.add(rootPath, model);\r
+                               }\r
+                       }\r
+\r
+                       WebMarkupContainer container = new WebMarkupContainer("row");\r
+                       add(container);\r
+                       container.add(new NestedRepositoryTreePanel("rowContent", Model.of(tree), accessRestrictionTranslations, enableLinks));\r
+\r
+                       Fragment fragment = new Fragment("headerContent", "groupRepositoryHeader", this);\r
+                       Fragment allCollapsible = new Fragment("allCollapsible", "tableAllCollapsible", this);\r
+                       fragment.add(allCollapsible);\r
+                       add(fragment);\r
+\r
+               } else if (app().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {\r
+                       List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();\r
+                       Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();\r
+                       for (RepositoryModel model : models) {\r
+                               String rootPath = StringUtils.getRootPath(model.name);\r
+                               if (StringUtils.isEmpty(rootPath)) {\r
+                                       // root repository\r
+                                       rootRepositories.add(model);\r
+                               } else {\r
+                                       // non-root, grouped repository\r
+                                       if (!groups.containsKey(rootPath)) {\r
+                                               groups.put(rootPath, new ArrayList<RepositoryModel>());\r
+                                       }\r
+                                       groups.get(rootPath).add(model);\r
+                               }\r
+                       }\r
+                       List<String> roots = new ArrayList<String>(groups.keySet());\r
+                       Collections.sort(roots);\r
+\r
+                       if (rootRepositories.size() > 0) {\r
+                               // inject the root repositories at the top of the page\r
+                               roots.add(0, "");\r
+                               groups.put("", rootRepositories);\r
+                       }\r
+\r
+                       List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();\r
+                       for (String root : roots) {\r
+                               List<RepositoryModel> subModels = groups.get(root);\r
+                               ProjectModel project = app().projects().getProjectModel(root);\r
+                               GroupRepositoryModel group = new GroupRepositoryModel(project == null ? root : project.name, subModels.size());\r
+                               if (project != null) {\r
+                                       group.title = project.title;\r
+                                       group.description = project.description;\r
+                               }\r
+                               groupedModels.add(group);\r
+                               Collections.sort(subModels);\r
+                               groupedModels.addAll(subModels);\r
+                       }\r
+                       dp = new ListDataProvider<RepositoryModel>(groupedModels);\r
+               } else {\r
+                       dp = new SortableRepositoriesProvider(models);\r
+               }\r
+\r
+               if (dp != null) {\r
+               final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);\r
+\r
+               DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {\r
+                       private static final long serialVersionUID = 1L;\r
+                       int counter;\r
+                       String currGroupName;\r
+\r
+                       @Override\r
+                       protected void onBeforeRender() {\r
+                               super.onBeforeRender();\r
+                               counter = 0;\r
+                       }\r
+\r
+                       @Override\r
+                       public void populateItem(final Item<RepositoryModel> item) {\r
+                               final RepositoryModel entry = item.getModelObject();\r
+                               if (entry instanceof GroupRepositoryModel) {\r
+                                       GroupRepositoryModel groupRow = (GroupRepositoryModel) entry;\r
+                                       currGroupName = entry.name;\r
+                                       Fragment row = new Fragment("rowContent", "groupRepositoryRow", this);\r
+                                       if(collapsibleRepoGroups == CollapsibleRepositorySetting.EXPANDED) {\r
+                                               Fragment groupCollapsible = new Fragment("groupCollapsible", "tableGroupMinusCollapsible", this);\r
+                                               row.add(groupCollapsible);\r
+                                       } else if(collapsibleRepoGroups == CollapsibleRepositorySetting.COLLAPSED) {\r
+                                               Fragment groupCollapsible = new Fragment("groupCollapsible", "tableGroupPlusCollapsible", this);\r
+                                               row.add(groupCollapsible);\r
+                                       } else {\r
+                                               Fragment groupCollapsible = new Fragment("groupCollapsible", "emptyFragment", this);\r
+                                               row.add(groupCollapsible);\r
+                                       }\r
+                                       item.add(row);\r
+\r
+                                       String name = groupRow.name;\r
+                                       if (name.startsWith(ModelUtils.getUserRepoPrefix())) {\r
+                                               // user page\r
+                                               String username = ModelUtils.getUserNameFromRepoPath(name);\r
+                                               UserModel user = app().users().getUserModel(username);\r
+                                               row.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()) + " (" + groupRow.count + ")", UserPage.class, WicketUtils.newUsernameParameter(username)));\r
+                                               row.add(new Label("groupDescription", getString("gb.personalRepositories")));\r
+                                       } else {\r
+                                               // project page\r
+                                               row.add(new LinkPanel("groupName", null, groupRow.toString(), ProjectPage.class, WicketUtils.newProjectParameter(entry.name)));\r
+                                               row.add(new Label("groupDescription", entry.description == null ? "":entry.description));\r
+                                       }\r
+                                       WicketUtils.setCssClass(item, "group collapsible");\r
+                                       // reset counter so that first row is light background\r
+                                       counter = 0;\r
+                                       return;\r
+                               }\r
+                               Fragment row = new Fragment("rowContent", "repositoryRow", this);\r
+                               item.add(row);\r
+\r
+                               // show colored repository type icon\r
+                               Fragment iconFragment;\r
+                               if (entry.isMirror) {\r
+                                       iconFragment = new Fragment("repoIcon", "mirrorIconFragment", this);\r
+                               } else if (entry.isFork()) {\r
+                                       iconFragment = new Fragment("repoIcon", "forkIconFragment", this);\r
+                               } else if (entry.isBare) {\r
+                                       iconFragment = new Fragment("repoIcon", "repoIconFragment", this);\r
+                               } else {\r
+                                       iconFragment = new Fragment("repoIcon", "cloneIconFragment", this);\r
+                               }\r
+                               if (showSwatch) {\r
+                                       WicketUtils.setCssStyle(iconFragment, "color:" + StringUtils.getColor(entry.toString()));\r
+                               }\r
+                               row.add(iconFragment);\r
+\r
+                               // try to strip group name for less cluttered list\r
+                               String repoName = entry.toString();\r
+                               if (!StringUtils.isEmpty(currGroupName) && (repoName.indexOf('/') > -1)) {\r
+                                       repoName = repoName.substring(currGroupName.length() + 1);\r
+                               }\r
+\r
+                               if (linksActive) {\r
+                                       Class<? extends BasePage> linkPage = SummaryPage.class;\r
+                                       PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);\r
+                                       row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));\r
+                                       row.add(new LinkPanel("repositoryDescription", "list", entry.description,\r
+                                                       linkPage, pp));\r
+                               } else {\r
+                                       // no links like on a federation page\r
+                                       row.add(new Label("repositoryName", repoName));\r
+                                       row.add(new Label("repositoryDescription", entry.description));\r
+                               }\r
+                               if (entry.hasCommits) {\r
+                                       // Existing repository\r
+                                       row.add(new Label("repositorySize", entry.size).setVisible(showSize));\r
+                               } else {\r
+                                       // New repository\r
+                                       row.add(new Label("repositorySize", "<span class='empty'>(" + getString("gb.empty") + ")</span>")\r
+                                                       .setEscapeModelStrings(false));\r
+                               }\r
+\r
+                               if (entry.isSparkleshared()) {\r
+                                       row.add(WicketUtils.newImage("sparkleshareIcon", "star_16x16.png",\r
+                                                       getString("gb.isSparkleshared")));\r
+                               } else {\r
+                                       row.add(WicketUtils.newClearPixel("sparkleshareIcon").setVisible(false));\r
+                               }\r
+\r
+                               if (!entry.isMirror && entry.isFrozen) {\r
+                                       row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png",\r
+                                                       getString("gb.isFrozen")));\r
+                               } else {\r
+                                       row.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false));\r
+                               }\r
+\r
+                               if (entry.isFederated) {\r
+                                       row.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png",\r
+                                                       getString("gb.isFederated")));\r
+                               } else {\r
+                                       row.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false));\r
+                               }\r
+\r
+                               if (entry.isMirror) {\r
+                                       row.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png",\r
+                                                       getString("gb.isMirror")));\r
+                               } else {\r
+                                       switch (entry.accessRestriction) {\r
+                                       case NONE:\r
+                                               row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));\r
+                                               break;\r
+                                       case PUSH:\r
+                                               row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png",\r
+                                                               accessRestrictionTranslations.get(entry.accessRestriction)));\r
+                                               break;\r
+                                       case CLONE:\r
+                                               row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png",\r
+                                                               accessRestrictionTranslations.get(entry.accessRestriction)));\r
+                                               break;\r
+                                       case VIEW:\r
+                                               row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png",\r
+                                                               accessRestrictionTranslations.get(entry.accessRestriction)));\r
+                                               break;\r
+                                       default:\r
+                                               row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));\r
+                                       }\r
+                               }\r
+\r
+                               String owner = "";\r
+                               if (!ArrayUtils.isEmpty(entry.owners)) {\r
+                                       // display first owner\r
+                                       for (String username : entry.owners) {\r
+                                               UserModel ownerModel = app().users().getUserModel(username);\r
+                                               if (ownerModel != null) {\r
+                                                       owner = ownerModel.getDisplayName();\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       if (entry.owners.size() > 1) {\r
+                                               owner += ", ...";\r
+                                       }\r
+                               }\r
+                               Label ownerLabel = new Label("repositoryOwner", owner);\r
+                               WicketUtils.setHtmlTooltip(ownerLabel, ArrayUtils.toString(entry.owners));\r
+                               row.add(ownerLabel);\r
+\r
+                               String lastChange;\r
+                               if (entry.lastChange.getTime() == 0) {\r
+                                       lastChange = "--";\r
+                               } else {\r
+                                       lastChange = getTimeUtils().timeAgo(entry.lastChange);\r
+                               }\r
+                               Label lastChangeLabel = new Label("repositoryLastChange", lastChange);\r
+                               row.add(lastChangeLabel);\r
+                               WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange));\r
+                               if (!StringUtils.isEmpty(entry.lastChangeAuthor)) {\r
+                                       WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor);\r
+                               }\r
+\r
+                               WicketUtils.setAlternatingBackground(item, counter);\r
+                               counter++;\r
+                       }\r
+               };\r
+               add(dataView);\r
+\r
+               if (dp instanceof SortableDataProvider<?>) {\r
+                       // add sortable header\r
+                       SortableDataProvider<?> sdp = (SortableDataProvider<?>) dp;\r
+                       Fragment fragment = new Fragment("headerContent", "flatRepositoryHeader", this);\r
+                       fragment.add(newSort("orderByRepository", SortBy.repository, sdp, dataView));\r
+                       fragment.add(newSort("orderByDescription", SortBy.description, sdp, dataView));\r
+                       fragment.add(newSort("orderByOwner", SortBy.owner, sdp, dataView));\r
+                       fragment.add(newSort("orderByDate", SortBy.date, sdp, dataView));\r
+                       add(fragment);\r
+               } else {\r
+                       // not sortable\r
+                       Fragment fragment = new Fragment("headerContent", "groupRepositoryHeader", this);\r
+                       if(collapsibleRepoGroups == CollapsibleRepositorySetting.EXPANDED ||\r
+                                       collapsibleRepoGroups == CollapsibleRepositorySetting.COLLAPSED) {\r
+                               Fragment allCollapsible = new Fragment("allCollapsible", "tableAllCollapsible", this);\r
+                               fragment.add(allCollapsible);\r
+                       } else {\r
+                               Fragment allCollapsible = new Fragment("allCollapsible", "emptyFragment", this);\r
+                               fragment.add(allCollapsible);\r
+                       }\r
+                       add(fragment);\r
+               }\r
+               }\r
+       }\r
+\r
+       private static class GroupRepositoryModel extends RepositoryModel {\r
+\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               int count;\r
+               String title;\r
+\r
+               GroupRepositoryModel(String name, int count) {\r
+                       super(name, "", "", new Date(0));\r
+                       this.count = count;\r
+               }\r
+\r
+               @Override\r
+               public String toString() {\r
+                       return (StringUtils.isEmpty(title) ? name  : title) + " (" + count + ")";\r
+               }\r
+       }\r
+\r
+       protected enum SortBy {\r
+               repository, description, owner, date;\r
+       }\r
+\r
+       protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp,\r
+                       final DataView<?> dataView) {\r
+               return new OrderByBorder(wicketId, field.name(), dp) {\r
+                       private static final long serialVersionUID = 1L;\r
+\r
+                       @Override\r
+                       protected void onSortChanged() {\r
+                               dataView.setCurrentPage(0);\r
+                       }\r
+               };\r
+       }\r
+\r
+       private static class SortableRepositoriesProvider extends SortableDataProvider<RepositoryModel> {\r
+\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               private List<RepositoryModel> list;\r
+\r
+               protected SortableRepositoriesProvider(List<RepositoryModel> list) {\r
+                       this.list = list;\r
+                       setSort(SortBy.date.name(), false);\r
+               }\r
+\r
+               @Override\r
+               public int size() {\r
+                       if (list == null) {\r
+                               return 0;\r
+                       }\r
+                       return list.size();\r
+               }\r
+\r
+               @Override\r
+               public IModel<RepositoryModel> model(RepositoryModel header) {\r
+                       return new Model<RepositoryModel>(header);\r
+               }\r
+\r
+               @Override\r
+               public Iterator<RepositoryModel> iterator(int first, int count) {\r
+                       SortParam sp = getSort();\r
+                       String prop = sp.getProperty();\r
+                       final boolean asc = sp.isAscending();\r
+\r
+                       if (prop == null || prop.equals(SortBy.date.name())) {\r
+                               Collections.sort(list, new Comparator<RepositoryModel>() {\r
+                                       @Override\r
+                                       public int compare(RepositoryModel o1, RepositoryModel o2) {\r
+                                               if (asc) {\r
+                                                       return o1.lastChange.compareTo(o2.lastChange);\r
+                                               }\r
+                                               return o2.lastChange.compareTo(o1.lastChange);\r
+                                       }\r
+                               });\r
+                       } else if (prop.equals(SortBy.repository.name())) {\r
+                               Collections.sort(list, new Comparator<RepositoryModel>() {\r
+                                       @Override\r
+                                       public int compare(RepositoryModel o1, RepositoryModel o2) {\r
+                                               if (asc) {\r
+                                                       return o1.name.compareTo(o2.name);\r
+                                               }\r
+                                               return o2.name.compareTo(o1.name);\r
+                                       }\r
+                               });\r
+                       } else if (prop.equals(SortBy.owner.name())) {\r
+                               Collections.sort(list, new Comparator<RepositoryModel>() {\r
+                                       @Override\r
+                                       public int compare(RepositoryModel o1, RepositoryModel o2) {\r
+                                               String own1 = ArrayUtils.toString(o1.owners);\r
+                                               String own2 = ArrayUtils.toString(o2.owners);\r
+                                               if (asc) {\r
+                                                       return own1.compareTo(own2);\r
+                                               }\r
+                                               return own2.compareTo(own1);\r
+                                       }\r
+                               });\r
+                       } else if (prop.equals(SortBy.description.name())) {\r
+                               Collections.sort(list, new Comparator<RepositoryModel>() {\r
+                                       @Override\r
+                                       public int compare(RepositoryModel o1, RepositoryModel o2) {\r
+                                               if (asc) {\r
+                                                       return o1.description.compareTo(o2.description);\r
+                                               }\r
+                                               return o2.description.compareTo(o1.description);\r
+                                       }\r
+                               });\r
+                       }\r
+                       return list.subList(first, first + count).iterator();\r
+               }\r
+       }\r
 }\r