You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by sm...@apache.org on 2014/11/11 21:35:30 UTC

[20/27] directory-fortress-commander git commit: change package structure and names, pom improvements, license

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/PwPolicyListPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/PwPolicyListPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/PwPolicyListPanel.java
new file mode 100644
index 0000000..005ae8a
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/PwPolicyListPanel.java
@@ -0,0 +1,315 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.inmethod.grid.IGridColumn;
+import com.inmethod.grid.SizeUnit;
+import com.inmethod.grid.column.PropertyColumn;
+import com.inmethod.grid.treegrid.TreeGrid;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.PwPolicyListModel;
+import org.apache.directory.fortress.web.SaveModelEvent;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.directory.fortress.core.rbac.FortEntity;
+import org.apache.directory.fortress.core.rbac.PwPolicy;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * User: Shawn McKinney
+ * Date: 6/12/13
+ */
+public class PwPolicyListPanel extends FormComponentPanel
+{
+    private static final Logger log = Logger.getLogger(PwPolicyListPanel.class.getName());
+    private Form listForm;
+    private DefaultTreeModel treeModel;
+    private DefaultMutableTreeNode node;
+    private TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid;
+    private DefaultMutableTreeNode rootNode;
+    private String searchVal;
+
+    public PwPolicyListPanel(String id)
+    {
+        super(id);
+        PwPolicyListModel policyListModel = new PwPolicyListModel(new PwPolicy(""), GlobalUtils.getRbacSession( this ) );
+        setDefaultModel(policyListModel);
+        List<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>> columns =
+            new ArrayList<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>>();
+        columns.add(new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+            Model.of("Policy Name"), "userObject.name"));
+
+        PropertyColumn minAge = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Min Age"), "userObject.minAge");
+        minAge.setInitialSize(60);
+        columns.add(minAge);
+
+        PropertyColumn maxAge = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Max Age"), "userObject.maxAge");
+        maxAge.setInitialSize(75);
+        columns.add(maxAge);
+
+        PropertyColumn inHistory = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("History"), "userObject.inHistory");
+        inHistory.setInitialSize(50);
+        columns.add(inHistory);
+
+        PropertyColumn minLength = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Min Len"), "userObject.minLength");
+        minLength.setInitialSize(60);
+        columns.add(minLength);
+
+        PropertyColumn expireWarning = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Expire Warning"), "userObject.expireWarning");
+        expireWarning.setInitialSize(115);
+        columns.add(expireWarning);
+
+        PropertyColumn graceLoginLimit = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Grace"), "userObject.graceLoginLimit");
+        graceLoginLimit.setInitialSize(50);
+        columns.add(graceLoginLimit);
+
+        PropertyColumn lockout = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Lockout"), "userObject.lockout");
+        lockout.setInitialSize(60);
+        columns.add(lockout);
+
+        PropertyColumn lockoutDuration = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Lockout Duration"), "userObject.lockoutDuration");
+        lockoutDuration.setInitialSize(125);
+        columns.add(lockoutDuration);
+
+        PropertyColumn maxFailure = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Max Failure"), "userObject.maxFailure");
+        maxFailure.setInitialSize(80);
+        columns.add(maxFailure);
+
+        PropertyColumn failureCountInterval = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Interval"), "userObject.failureCountInterval");
+        failureCountInterval.setInitialSize(60);
+        columns.add(failureCountInterval);
+
+        PropertyColumn mustChange = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Must Change"), "userObject.mustChange");
+        mustChange.setInitialSize(90);
+        columns.add(mustChange);
+
+        PropertyColumn allowUserChange = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Allow Change"), "userObject.allowUserChange");
+        allowUserChange.setInitialSize(95);
+        columns.add(allowUserChange);
+
+        PropertyColumn safeModify = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Safe Modify"), "userObject.safeModify");
+        safeModify.setInitialSize(90);
+        columns.add(safeModify);
+
+/*
+        PropertyColumn checkQuality = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Check Quality"), "userObject.checkQuality");
+        checkQuality.setInitialSize(100);
+        columns.add(checkQuality);
+*/
+
+        List<PwPolicy> policies = (List<PwPolicy>) getDefaultModel().getObject();
+        treeModel = createTreeModel(policies);
+        grid = new TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String>("policytreegrid", treeModel, columns)
+        {
+            @Override
+            public void selectItem(IModel itemModel, boolean selected)
+            {
+                node = (DefaultMutableTreeNode) itemModel.getObject();
+                if(!node.isRoot())
+                {
+                    PwPolicy policy = (PwPolicy) node.getUserObject();
+                    log.debug("TreeGrid.addGrid.selectItem selected policy =" + policy.getName());
+                    if (super.isItemSelected(itemModel))
+                    {
+                        log.debug("TreeGrid.addGrid.selectItem item is selected");
+                        super.selectItem(itemModel, false);
+                    }
+                    else
+                    {
+                        super.selectItem(itemModel, true);
+                        SelectModelEvent.send(getPage(), this, policy);
+                    }
+                }
+            }
+        };
+        grid.setContentHeight(50, SizeUnit.EM);
+        grid.setAllowSelectMultiple(false);
+        grid.setClickRowToSelect(true);
+        grid.setClickRowToDeselect(false);
+        grid.setSelectToEdit(false);
+        // expand the root node
+        grid.getTreeState().expandNode((TreeNode) treeModel.getRoot());
+        this.listForm = new Form("form");
+        this.listForm.add(grid);
+        grid.setOutputMarkupId(true);
+        TextField searchValFld = new TextField(GlobalIds.SEARCH_VAL, new PropertyModel<String>(this, GlobalIds.SEARCH_VAL));
+        this.listForm.add(searchValFld);
+
+        this.listForm.add(new AjaxSubmitLink(GlobalIds.SEARCH)
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                log.debug(".search onSubmit");
+                info("Searching Policies...");
+                if(!VUtil.isNotNullOrEmpty(searchVal))
+                {
+                    searchVal = "";
+                }
+                PwPolicy srchPolicy = new PwPolicy(searchVal);
+                setDefaultModel(new PwPolicyListModel(srchPolicy, GlobalUtils.getRbacSession( this )));
+                treeModel.reload();
+                rootNode.removeAllChildren();
+                List<PwPolicy> policies = (List<PwPolicy>) getDefaultModelObject();
+                if(VUtil.isNotNullOrEmpty(policies))
+                {
+                    for (PwPolicy policy : policies)
+                        rootNode.add(new DefaultMutableTreeNode(policy));
+                    info("Search returned " + policies.size() + " matching objects");
+                }
+                else
+                {
+                    info("No matching objects found");
+                }
+                target.add(grid);
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                log.warn(".search.onError");
+                target.add();
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+        add(this.listForm);
+    }
+
+    @Override
+    public void onEvent(IEvent event)
+    {
+        if (event.getPayload() instanceof SaveModelEvent)
+        {
+            SaveModelEvent modelEvent = (SaveModelEvent) event.getPayload();
+            switch(modelEvent.getOperation())
+            {
+                case ADD:
+                    add(modelEvent.getEntity());
+                    break;
+                case UPDATE:
+                    modelChanged();
+                    break;
+                case DELETE:
+                    prune();
+                    break;
+                default:
+                    break;
+            }
+            AjaxRequestTarget target = ((SaveModelEvent) event.getPayload()).getAjaxRequestTarget();
+            target.add(grid);
+            log.debug(".onEvent SaveModelEvent: " + target.toString());
+        }
+    }
+
+    private void removeSelectedItems(TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid)
+    {
+        Collection<IModel<DefaultMutableTreeNode>> selected = grid.getSelectedItems();
+        for (IModel<DefaultMutableTreeNode> model : selected)
+        {
+            DefaultMutableTreeNode node = model.getObject();
+            treeModel.removeNodeFromParent(node);
+            PwPolicy policy = (PwPolicy) node.getUserObject();
+            log.debug(".removeSelectedItems policy node: " + policy.getName());
+            List<PwPolicy> policies = ((List<PwPolicy>) getDefaultModel().getObject());
+            policies.remove(policy.getName());
+        }
+    }
+
+    private DefaultTreeModel createTreeModel(List<PwPolicy> policies)
+    {
+        DefaultTreeModel model;
+        PwPolicy root = new PwPolicy();
+        //root.setName("Policies");
+        rootNode = new DefaultMutableTreeNode(root);
+        model = new DefaultTreeModel(rootNode);
+        if (policies == null)
+            log.debug("no Policies found");
+        else
+        {
+            log.debug("Policies found:" + policies.size());
+            for (PwPolicy policy : policies)
+                rootNode.add(new DefaultMutableTreeNode(policy));
+        }
+        return model;
+    }
+
+    public void add(FortEntity entity)
+    {
+        if (getDefaultModelObject() != null)
+        {
+            List<PwPolicy> policies = ((List<PwPolicy>) getDefaultModelObject());
+            policies.add((PwPolicy) entity);
+            treeModel.insertNodeInto(new DefaultMutableTreeNode(entity), rootNode, policies.size());
+        }
+    }
+
+    public void prune()
+    {
+        removeSelectedItems(grid);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/PwPolicySearchModalPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/PwPolicySearchModalPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/PwPolicySearchModalPanel.java
new file mode 100644
index 0000000..b442d7d
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/PwPolicySearchModalPanel.java
@@ -0,0 +1,149 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.PageableListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.directory.fortress.core.PwPolicyMgr;
+import org.apache.directory.fortress.core.rbac.PwPolicy;
+
+/**
+ *
+ * @author Shawn McKinney
+ * @version $Rev$
+ */
+public class PwPolicySearchModalPanel extends Panel
+{
+    @SpringBean
+    private PwPolicyMgr pwPolicyMgr;
+    private static final Logger LOG = Logger.getLogger(PwPolicySearchModalPanel.class.getName());
+    private ModalWindow window;
+    private PwPolicy policySelection;
+    private String policySearchVal;
+
+    /**
+     * @param id
+     */
+    public PwPolicySearchModalPanel( String id, ModalWindow window)
+    {
+        super( id );
+        // TODO: add later:
+        //this.pwPolicyMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.window = window;
+        loadPanel();
+    }
+
+    public void loadPanel()
+    {
+        LoadableDetachableModel requests = getListViewModel();
+        PageableListView policyView = createListView( requests );
+        add( policyView );
+        add( new AjaxPagingNavigator( "policynavigator", policyView ) );
+    }
+
+    private PageableListView createListView( final LoadableDetachableModel requests )
+    {
+        final PageableListView listView = new PageableListView( "policydataview", requests, 16 )
+        {
+            @Override
+            protected void populateItem( final ListItem item )
+            {
+                final PwPolicy modelObject = ( PwPolicy ) item.getModelObject();
+                item.add( new AjaxLink<Void>( "select" )
+                {
+                    private static final long serialVersionUID = 1L;
+
+                    @Override
+                    public void onClick(AjaxRequestTarget target)
+                    {
+                        policySelection = modelObject;
+                        window.close( target );
+                    }
+                } );
+
+                item.add( new Label( "name", new PropertyModel( item.getModel(), "name" ) ) );
+                item.add( new Label( "minAge", new PropertyModel( item.getModel(), "minAge" ) ) );
+                item.add( new Label( "maxAge", new PropertyModel( item.getModel(), "maxAge" ) ) );
+                item.add( new Label( "inHistory", new PropertyModel( item.getModel(), "inHistory" ) ) );
+                item.add( new Label( "minLength", new PropertyModel( item.getModel(), "minLength" ) ) );
+                item.add( new Label( "expireWarning", new PropertyModel( item.getModel(), "expireWarning" ) ) );
+                item.add( new Label( "graceLoginLimit", new PropertyModel( item.getModel(), "graceLoginLimit" ) ) );
+                item.add( new Label( "lockout", new PropertyModel( item.getModel(), "lockout" ) ) );
+                item.add( new Label( "lockoutDuration", new PropertyModel( item.getModel(), "lockoutDuration" ) ) );
+                item.add( new Label( "maxFailure", new PropertyModel( item.getModel(), "maxFailure" ) ) );
+                item.add( new Label( "failureCountInterval", new PropertyModel( item.getModel(), "failureCountInterval" ) ) );
+                item.add( new Label( "mustChange", new PropertyModel( item.getModel(), "mustChange" ) ) );
+                item.add( new Label( "allowUserChange", new PropertyModel( item.getModel(), "allowUserChange" ) ) );
+                item.add( new Label( "safeModify", new PropertyModel( item.getModel(), "safeModify" ) ) );
+
+            }
+        };
+        return listView;
+    }
+
+    private LoadableDetachableModel getListViewModel()
+    {
+        final LoadableDetachableModel ret = new LoadableDetachableModel()
+        {
+            @Override
+            protected Object load()
+            {
+                List<PwPolicy> policies = null;
+                try
+                {
+                    policySelection = null;
+                    if(policySearchVal == null)
+                        policySearchVal = "";
+                    policies = pwPolicyMgr.search( policySearchVal );
+                }
+                catch ( org.apache.directory.fortress.core.SecurityException se )
+                {
+                    String error = "loadPanel caught SecurityException=" + se;
+                    LOG.error( error );
+                }
+                return policies;
+            }
+        };
+        return ret;
+    }
+
+    public PwPolicy getPolicySelection()
+    {
+        return policySelection;
+    }
+
+    public void setSearchVal( String searchVal )
+    {
+        this.policySearchVal = searchVal;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/RequestMod.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/RequestMod.java b/src/main/java/org/apache/directory/fortress/web/panel/RequestMod.java
new file mode 100644
index 0000000..bbaa729
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/RequestMod.java
@@ -0,0 +1,126 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import java.io.Serializable;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ *          Date: 8/11/13
+ */
+class RequestMod implements Serializable
+{
+    enum TYPE
+    {
+        ADD,
+        UPDATE,
+        DELETE,
+        UNKNOWN
+    }
+
+    private int index;
+    private TYPE type;
+    private String name;
+    private String value;
+
+    RequestMod( int index, String name, String value )
+    {
+        this.type = type;
+        this.index = index;
+        this.name = name;
+        this.value = value;
+    }
+
+    RequestMod( String name )
+    {
+        this.name = name;
+    }
+
+    public int getIndex()
+    {
+        return index;
+    }
+
+    public TYPE getType()
+    {
+        return type;
+    }
+
+    public void setType( TYPE type )
+    {
+        this.type = type;
+    }
+
+    public void setIndex( int index )
+    {
+        this.index = index;
+
+    }
+
+    public String getValue()
+    {
+        return value;
+    }
+
+    public void setValue( String value )
+    {
+        this.value = value;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        RequestMod that = ( RequestMod ) o;
+
+        if ( !name.equals( that.name ) )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return name.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/RoleAdminDetailPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/RoleAdminDetailPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/RoleAdminDetailPanel.java
new file mode 100644
index 0000000..0669989
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/RoleAdminDetailPanel.java
@@ -0,0 +1,444 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.googlecode.wicket.kendo.ui.form.button.AjaxButton;
+import com.googlecode.wicket.kendo.ui.form.combobox.ComboBox;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.CheckBox;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.core.rbac.AdminRole;
+import org.apache.directory.fortress.core.rbac.OrgUnit;
+import org.apache.directory.fortress.core.rbac.UserRole;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import java.util.List;
+
+/**
+ * @author Shawn McKinney
+ * @version $Rev$
+ *          Date: 8/12/13
+ */
+public class RoleAdminDetailPanel extends Panel
+{
+    private static final Logger LOG = Logger.getLogger( RoleAdminDetailPanel.class.getName() );
+    public static final String PERMOU_SELECTION = "permouSelection";
+    public static final String USEROU_SELECTION = "userouSelection";
+    public static final String ROLE_ASSIGN_MODAL = "role-assign-modal";
+    private List<String> permous;
+    private List<String> userous;
+    private ComboBox<String> userouCB;
+    private ComboBox<String> permouCB;
+    private TextField beginRangeTF;
+    private TextField endRangeTF;
+    private String userouSelection;
+    private String permouSelection;
+
+    public RoleAdminDetailPanel( String id, final IModel roleModel )
+    {
+        super( id, roleModel );
+
+        permouCB = new ComboBox<String>( GlobalIds.OS_P, new PropertyModel<String>( this, PERMOU_SELECTION ), permous );
+        permouCB.setOutputMarkupId( true );
+        add( permouCB );
+        addPermOUSearchModal();
+
+        userouCB = new ComboBox<String>( GlobalIds.OS_U, new PropertyModel<String>( this, USEROU_SELECTION ), userous );
+        userouCB.setOutputMarkupId( true );
+        add( userouCB );
+        addUserOUSearchModal();
+
+        beginRangeTF = new TextField( GlobalIds.BEGIN_RANGE );
+        beginRangeTF.setRequired( false );
+        beginRangeTF.setOutputMarkupId( true );
+        add( beginRangeTF );
+        addBeginRoleSearchModal();
+
+        CheckBox beginInclusiveCB = new CheckBox( GlobalIds.BEGIN_INCLUSIVE );
+        beginInclusiveCB.setRequired( false );
+        add( beginInclusiveCB );
+
+        endRangeTF = new TextField( GlobalIds.END_RANGE );
+        endRangeTF.setRequired( false );
+        endRangeTF.setOutputMarkupId( true );
+        add( endRangeTF );
+        addEndRoleSearchModal();
+
+        CheckBox endInclusiveCB = new CheckBox( GlobalIds.END_INCLUSIVE );
+        endInclusiveCB.setRequired( false );
+        add( endInclusiveCB );
+
+        setOutputMarkupId( true );
+    }
+
+    private void addPermOUSearchModal()
+    {
+        final ModalWindow permousModalWindow;
+        add( permousModalWindow = new ModalWindow( "permoumodal" ) );
+        final OUSearchModalPanel permouSearchModalPanel = new OUSearchModalPanel( permousModalWindow.getContentId(),
+            permousModalWindow, false );
+        permousModalWindow.setContent( permouSearchModalPanel );
+        permousModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                OrgUnit ou = permouSearchModalPanel.getSelection();
+                if ( ou != null )
+                {
+                    permouSelection = ou.getName();
+                    AdminRole adminRole = (AdminRole)getDefaultModelObject();
+                    adminRole.setOsP( permouSelection );
+                    target.add( permouCB );
+                }
+            }
+        } );
+
+        add( new AjaxButton( GlobalIds.PERMOU_SEARCH )
+        {
+            @Override
+            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+            {
+                String msg = "clicked on permission OU search";
+                msg += permouSelection != null ? ": " + permouSelection : "";
+                permouSearchModalPanel.setSearchVal( permouSelection );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                permousModalWindow.show( target );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+
+        permousModalWindow.setTitle( "Perm Organization Selection Modal" );
+        permousModalWindow.setInitialWidth( 450 );
+        permousModalWindow.setInitialHeight( 450 );
+        permousModalWindow.setCookieName( "permou-modal" );
+
+        add( new AjaxButton( "permou.delete" )
+        {
+            @Override
+            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+            {
+                String msg = "clicked on permous.delete";
+                if ( VUtil.isNotNullOrEmpty( permouSelection ) )
+                {
+                    msg += " selection:" + permouSelection;
+                    AdminRole adminRole = ( AdminRole ) form.getModel().getObject();
+                    if ( adminRole.getOsP() != null )
+                    {
+                        adminRole.getOsP().remove( permouSelection );
+                        permous.remove( permouSelection );
+                        permouSelection = "";
+                        target.add( permouCB );
+                        msg += ", was removed from local, commit to persist changes on server";
+                    }
+                    else
+                    {
+                        msg += ", no action taken because org unit does not have parent set";
+                    }
+                }
+                else
+                {
+                    msg += ", no action taken because parents selection is empty";
+                }
+                LOG.debug( msg );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+    }
+
+    private void addUserOUSearchModal()
+    {
+        final ModalWindow userousModalWindow;
+        add( userousModalWindow = new ModalWindow( "useroumodal" ) );
+        final OUSearchModalPanel userouSearchModalPanel = new OUSearchModalPanel( userousModalWindow.getContentId(),
+            userousModalWindow, true );
+        userousModalWindow.setContent( userouSearchModalPanel );
+        userousModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                OrgUnit ou = userouSearchModalPanel.getSelection();
+                if ( ou != null )
+                {
+                    userouSelection = ou.getName();
+                    AdminRole adminRole = (AdminRole)getDefaultModelObject();
+                    adminRole.setOsU( userouSelection );
+                    target.add( userouCB );
+                }
+            }
+        } );
+
+        add( new AjaxButton( GlobalIds.USEROU_SEARCH )
+        {
+            @Override
+            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+            {
+                String msg = "clicked on user OU search";
+                msg += userouSelection != null ? ": " + userouSelection : "";
+                userouSearchModalPanel.setSearchVal( userouSelection );
+                LOG.debug( msg );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                userousModalWindow.show( target );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+
+        userousModalWindow.setTitle( "User Organization Selection Modal" );
+        userousModalWindow.setInitialWidth( 450 );
+        userousModalWindow.setInitialHeight( 450 );
+        userousModalWindow.setCookieName( "permou-modal" );
+
+        add( new AjaxButton( "userou.delete" )
+        {
+            @Override
+            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+            {
+                String msg = "clicked on userous.delete";
+                if ( VUtil.isNotNullOrEmpty( userouSelection ) )
+                {
+                    msg += " selection:" + userouSelection;
+                    AdminRole adminRole = ( AdminRole ) form.getModel().getObject();
+                    if ( adminRole.getOsU() != null )
+                    {
+                        adminRole.getOsU().remove( userouSelection );
+                        userous.remove( userouSelection );
+                        userouSelection = "";
+                        target.add( userouCB );
+                        msg += ", was removed from local, commit to persist changes on server";
+                    }
+                    else
+                    {
+                        msg += ", no action taken because org unit does not have parent set";
+                    }
+                }
+                else
+                {
+                    msg += ", no action taken because parents selection is empty";
+                }
+                LOG.debug( msg );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+    }
+
+    private void addBeginRoleSearchModal()
+    {
+        final ModalWindow beginRoleModalWindow;
+        add( beginRoleModalWindow = new ModalWindow( "beginrolesmodal" ) );
+        final RoleSearchModalPanel beginRoleSearchModalPanel = new RoleSearchModalPanel( beginRoleModalWindow.getContentId(), beginRoleModalWindow, false );
+        beginRoleModalWindow.setContent( beginRoleSearchModalPanel );
+        beginRoleModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                UserRole userRole = beginRoleSearchModalPanel.getRoleSelection();
+                if ( userRole != null )
+                {
+                    AdminRole adminRole = ( AdminRole ) getDefaultModelObject();
+                    adminRole.setBeginRange( userRole.getName() );
+                    target.add( beginRangeTF );
+                }
+            }
+        } );
+
+        add( new AjaxButton( GlobalIds.BEGIN_RANGE_SEARCH )
+        {
+            @Override
+            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+            {
+                AdminRole adminRole = ( AdminRole ) form.getModel().getObject();
+                beginRoleSearchModalPanel.setRoleSearchVal( adminRole.getBeginRange() );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                beginRoleModalWindow.show( target );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+
+        beginRoleModalWindow.setTitle( "Begin Range Role Selection Modal" );
+        beginRoleModalWindow.setInitialWidth( 700 );
+        beginRoleModalWindow.setInitialHeight( 450 );
+        beginRoleModalWindow.setCookieName( ROLE_ASSIGN_MODAL );
+    }
+
+    private void addEndRoleSearchModal()
+    {
+        final ModalWindow endRoleModalWindow;
+        add( endRoleModalWindow = new ModalWindow( "endrolesmodal" ) );
+        final RoleSearchModalPanel endRoleSearchModalPanel = new RoleSearchModalPanel( endRoleModalWindow.getContentId(), endRoleModalWindow, false );
+        endRoleModalWindow.setContent( endRoleSearchModalPanel );
+        endRoleModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+        {
+            @Override
+            public void onClose( AjaxRequestTarget target )
+            {
+                UserRole userRole = endRoleSearchModalPanel.getRoleSelection();
+                if ( userRole != null )
+                {
+                    AdminRole adminRole = ( AdminRole ) getDefaultModelObject();
+                    adminRole.setEndRange( userRole.getName() );
+                    target.add( endRangeTF );
+                }
+            }
+        } );
+
+        add( new AjaxButton( GlobalIds.END_RANGE_SEARCH )
+        {
+            @Override
+            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+            {
+                AdminRole adminRole = ( AdminRole ) form.getModel().getObject();
+                endRoleSearchModalPanel.setRoleSearchVal( adminRole.getBeginRange() );
+                endRoleSearchModalPanel.setParentSearch( true );
+                target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                endRoleModalWindow.show( target );
+            }
+
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        } );
+
+        endRoleModalWindow.setTitle( "End Range Role Selection Modal" );
+        endRoleModalWindow.setInitialWidth( 700 );
+        endRoleModalWindow.setInitialHeight( 450 );
+        endRoleModalWindow.setCookieName( ROLE_ASSIGN_MODAL );
+    }
+
+    /**
+     * This api is needed for this class {@link org.apache.directory.fortress.web.panel.RoleDetailPanel} to 'push' its model value into this panel's combo box.
+     *
+     * @param permous
+     */
+    void setPermous( List<String> permous )
+    {
+        this.permous = permous;
+        permouCB = new ComboBox<String>( GlobalIds.OS_P, new PropertyModel<String>( this, PERMOU_SELECTION ), permous );
+        permouSelection = "";
+        addOrReplace( permouCB );
+    }
+
+    /**
+     * This api is needed for this class {@link org.apache.directory.fortress.web.panel.RoleDetailPanel} to 'push' its model value into this panel's combo box.
+     *
+     * @param userous
+     */
+    void setUserous( List<String> userous )
+    {
+        this.userous = userous;
+        userouCB = new ComboBox<String>( GlobalIds.OS_U, new PropertyModel<String>( this, USEROU_SELECTION ), userous );
+        userouSelection = "";
+        addOrReplace( userouCB );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/RoleDetailPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/RoleDetailPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/RoleDetailPanel.java
new file mode 100644
index 0000000..8b60a0b
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/RoleDetailPanel.java
@@ -0,0 +1,585 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.googlecode.wicket.jquery.core.JQueryBehavior;
+import com.googlecode.wicket.kendo.ui.form.button.AjaxButton;
+import com.googlecode.wicket.kendo.ui.form.combobox.ComboBox;
+import org.apache.directory.fortress.web.panel.ConstraintPanel;
+import org.apache.directory.fortress.web.panel.Displayable;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.SaveModelEvent;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxButton;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.directory.fortress.core.AdminMgr;
+import org.apache.directory.fortress.core.DelAdminMgr;
+import org.apache.directory.fortress.core.rbac.AdminRole;
+import org.apache.directory.fortress.core.rbac.FortEntity;
+import org.apache.directory.fortress.core.rbac.Role;
+import org.apache.directory.fortress.core.rbac.UserRole;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: kpmckinn
+ * Date: 2/26/13
+ * Time: 9:27 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class RoleDetailPanel extends Panel
+{
+    @SpringBean
+    private AdminMgr adminMgr;
+    @SpringBean
+    private DelAdminMgr delAdminMgr;
+    private static final Logger log = Logger.getLogger(RoleDetailPanel.class.getName());
+    private static final String PARENTS_SELECTION = "parentsSelection";
+    private Form editForm;
+    private Displayable display;
+    private boolean isAdmin;
+    private String objName;
+
+    public Form getForm()
+    {
+        return this.editForm;
+    }
+
+    public RoleDetailPanel(String id, Displayable display, final boolean isAdmin)
+    {
+        super(id);
+        this.isAdmin = isAdmin;
+        this.adminMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        this.delAdminMgr.setAdmin( GlobalUtils.getRbacSession( this ) );
+        if(isAdmin)
+        {
+            this.objName = GlobalIds.DEL_ADMIN_MGR;
+            this.editForm = new RoleDetailForm(GlobalIds.EDIT_FIELDS, new CompoundPropertyModel<AdminRole>(new AdminRole()));
+        }
+        else
+        {
+            this.objName = GlobalIds.ADMIN_MGR;
+            this.editForm = new RoleDetailForm(GlobalIds.EDIT_FIELDS, new CompoundPropertyModel<Role>(new Role()));
+        }
+
+        this.display = display;
+        add(editForm);
+    }
+
+    public class RoleDetailForm<T extends Serializable> extends Form
+    {
+        private static final String TEMPORAL_CONSTRAINTS_LABEL = "temporalConstraintsLabel";
+        private String temporalConstraintsLabel = "Temporal Constraints";
+        private ConstraintPanel constraintPanel;
+        private String internalId;
+        private ComboBox<String> parentsCB;
+        private Component component;
+        private String parentsSelection;
+        private List<String> parents = new ArrayList<String>();
+        private UserRole parentConstraint = new UserRole();
+        private RoleAdminDetailPanel auxPanel;
+
+        public RoleDetailForm(String id, final IModel<T> model)
+        {
+            super(id, model);
+            if(isAdmin)
+            {
+                auxPanel = new RoleAdminDetailPanel( GlobalIds.ROLEAUXPANEL, model );
+                add( auxPanel );
+            }
+            else
+            {
+                add( new WebMarkupContainer( GlobalIds.ROLEAUXPANEL ) );
+            }
+
+            this.add(new JQueryBehavior("#accordion", "accordion"));
+            constraintPanel = new ConstraintPanel("constraintpanel", model);
+            add(constraintPanel);
+            add( new Label( TEMPORAL_CONSTRAINTS_LABEL, new PropertyModel<String>( this,
+                TEMPORAL_CONSTRAINTS_LABEL ) ) );
+            TextField name = new TextField("name");
+            add(name);
+            TextField description = new TextField(GlobalIds.DESCRIPTION);
+            description.setRequired(false);
+            add(description);
+            Label iid = new Label("id");
+            add(iid);
+            parentsCB = new ComboBox<String>( GlobalIds.PARENTS, new PropertyModel<String>( this, PARENTS_SELECTION ), parents );
+            add(parentsCB);
+
+            add( new SecureIndicatingAjaxButton( GlobalIds.ADD, objName, GlobalIds.ADD_ROLE )
+            {
+                @Override
+                protected void onSubmit(AjaxRequestTarget target, Form form)
+                {
+                    log.debug(".onSubmit Add");
+                    T role = (T)form.getModel().getObject();
+                    updateEntityWithComboData((Role)role);
+                    try
+                    {
+                        String szRoleName;
+                        if(isAdmin)
+                        {
+                            delAdminMgr.addRole((AdminRole)role);
+                            szRoleName = ((AdminRole)role).getName();
+                        }
+                        else
+                        {
+                            adminMgr.addRole((Role)role);
+                            szRoleName = ((Role)role).getName();
+                        }
+
+                        parentsSelection = "";
+                        parents.add( parentsSelection );
+                        SaveModelEvent.send(getPage(), this, ( FortEntity )role, target, SaveModelEvent.Operations.ADD);
+                        component = editForm;
+                        String msg = "Role: " + szRoleName + " has been added";
+                        display.setMessage(msg);
+                    }
+                    catch (org.apache.directory.fortress.core.SecurityException se)
+                    {
+                        String error = ".onSubmit caught SecurityException=" + se;
+                        log.error(error);
+                        display.setMessage(error);
+                        display.display();
+                    }
+                }
+
+                @Override
+                public void onError(AjaxRequestTarget target, Form form)
+                {
+                    log.info("RoleDetailPanel.add.onError caught");
+                    target.add();
+                }
+                @Override
+                protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+                {
+                    super.updateAjaxAttributes( attributes );
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                    {
+                        @Override
+                        public CharSequence getFailureHandler( Component component )
+                        {
+                            return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                        }
+                    };
+                    attributes.getAjaxCallListeners().add( ajaxCallListener );
+                }
+            });
+            add( new SecureIndicatingAjaxButton( GlobalIds.COMMIT, objName, GlobalIds.UPDATE_ROLE )
+            {
+                @Override
+                protected void onSubmit(AjaxRequestTarget target, Form form)
+                {
+                    log.debug(".onSubmit Commit");
+                    T role = (T)form.getModel().getObject();
+                    updateEntityWithComboData((Role)role);
+                    try
+                    {
+                        String szRoleName;
+                        if(isAdmin)
+                        {
+                            delAdminMgr.updateRole((AdminRole)role);
+                            szRoleName = ((AdminRole)role).getName();
+                        }
+                        else
+                        {
+                            adminMgr.updateRole((Role)role);
+                            szRoleName = ((Role)role).getName();
+                        }
+                        String msg = "Role: " + szRoleName + " has been updated";
+                        SaveModelEvent.send(getPage(), this, ( FortEntity )role, target, SaveModelEvent.Operations.UPDATE);
+                        parentsSelection = "";
+                        component = editForm;
+                        display.setMessage(msg);
+                    }
+                    catch (org.apache.directory.fortress.core.SecurityException se)
+                    {
+                        String error = ".onSubmit caught SecurityException=" + se;
+                        log.error(error);
+                        display.setMessage(error);
+                        display.display();
+                    }
+                }
+
+                @Override
+                public void onError(AjaxRequestTarget target, Form form)
+                {
+                    log.warn("RoleDetailPanel.update.onError");
+                }
+                @Override
+                protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+                {
+                    super.updateAjaxAttributes( attributes );
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                    {
+                        @Override
+                        public CharSequence getFailureHandler( Component component )
+                        {
+                            return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                        }
+                    };
+                    attributes.getAjaxCallListeners().add( ajaxCallListener );
+                }
+            });
+            add( new SecureIndicatingAjaxButton( GlobalIds.DELETE, objName, GlobalIds.DELETE_ROLE )
+            {
+                @Override
+                protected void onSubmit(AjaxRequestTarget target, Form form)
+                {
+                    log.debug(".onSubmit Delete");
+                    T role = (T)form.getModel().getObject();
+                    try
+                    {
+                        String szRoleName;
+                        if(isAdmin)
+                        {
+                            delAdminMgr.deleteRole((AdminRole)role);
+                            szRoleName = ((AdminRole)role).getName();
+                            form.setModelObject( new AdminRole() );
+                        }
+                        else
+                        {
+                            adminMgr.deleteRole((Role)role);
+                            szRoleName = ((Role)role).getName();
+                            form.setModelObject( new Role() );
+                        }
+                        parentsSelection = "";
+                        parents = new ArrayList<String>();
+                        parentsCB = new ComboBox<String>( GlobalIds.PARENTS, new PropertyModel<String>( form, PARENTS_SELECTION ),parents );
+                        editForm.addOrReplace( parentsCB );
+                        modelChanged();
+                        String msg = "Role: " + szRoleName + " has been deleted";
+                        SaveModelEvent.send(getPage(), this, ( FortEntity )role, target, SaveModelEvent.Operations.DELETE);
+                        component = editForm;
+                        display.setMessage(msg);
+                    }
+                    catch (org.apache.directory.fortress.core.SecurityException se)
+                    {
+                        String error = ".onSubmit caught SecurityException=" + se;
+                        log.error(error);
+                        display.setMessage(error);
+                        display.display();
+                    }
+                }
+
+                @Override
+                public void onError(AjaxRequestTarget target, Form form)
+                {
+                    log.warn("RoleDetailPanel.delete.onError");
+                }
+                @Override
+                protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+                {
+                    super.updateAjaxAttributes( attributes );
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                    {
+                        @Override
+                        public CharSequence getFailureHandler( Component component )
+                        {
+                            return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                        }
+                    };
+                    attributes.getAjaxCallListeners().add( ajaxCallListener );
+                }
+            });
+            add(new AjaxSubmitLink(GlobalIds.CANCEL)
+            {
+                @Override
+                protected void onSubmit(AjaxRequestTarget target, Form form)
+                {
+                    if(isAdmin)
+                    {
+                        setModelObject(new AdminRole());
+                    }
+                    else
+                    {
+                        setModelObject(new Role());
+                    }
+                    parentsSelection = "";
+                    parents = new ArrayList<String>();
+                    parentsCB = new ComboBox<String>( GlobalIds.PARENTS, new PropertyModel<String>( form, PARENTS_SELECTION ),parents );
+                    modelChanged();
+                    editForm.addOrReplace( parentsCB );
+                    component = editForm;
+                    String msg = "Role cancelled input form";
+                    display.setMessage(msg);
+                }
+
+                @Override
+                public void onError(AjaxRequestTarget target, Form form)
+                {
+                    log.warn("RoleDetailPanel.cancel.onError");
+                }
+                @Override
+                protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+                {
+                    super.updateAjaxAttributes( attributes );
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                    {
+                        @Override
+                        public CharSequence getFailureHandler( Component component )
+                        {
+                            return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                        }
+                    };
+                    attributes.getAjaxCallListeners().add( ajaxCallListener );
+                }
+            });
+
+            if(isAdmin)
+            {
+                add( new Label( "roleDetailLabel", "Admin Role Detail" ) );
+            }
+            else
+            {
+                add( new Label( "roleDetailLabel", "RBAC Role Detail" ) );
+            }
+            addRoleSearchModal();
+            add( new AjaxButton( "roles.delete" )
+            {
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+                {
+                    String msg = "clicked on roles.delete";
+                    if ( VUtil.isNotNullOrEmpty( parentsSelection ) )
+                    {
+                        msg += " selection:" + parentsSelection;
+                        Role role = ( Role ) form.getModel().getObject();
+                        if ( role.getParents() != null )
+                        {
+                            role.getParents().remove( parentsSelection );
+                            parents.remove(  parentsSelection );
+                            parentsSelection = "";
+                            component = editForm;
+                            msg += ", was removed from local, commit to persist changes on server";
+                        }
+                        else
+                        {
+                            msg += ", no action taken because role does not have parent set";
+                        }
+                    }
+                    else
+                    {
+                        msg += ", no action taken because parent selection is empty";
+                    }
+                    display.setMessage( msg );
+                    log.debug( msg );
+                }
+                @Override
+                protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+                {
+                    super.updateAjaxAttributes( attributes );
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                    {
+                        @Override
+                        public CharSequence getFailureHandler( Component component )
+                        {
+                            return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                        }
+                    };
+                    attributes.getAjaxCallListeners().add( ajaxCallListener );
+                }
+            } );
+            setOutputMarkupId(true);
+        }
+
+        private void updateEntityWithComboData(Role role)
+        {
+            if(VUtil.isNotNullOrEmpty(parentsSelection))
+            {
+                role.setParent( parentsSelection );
+                parents.add( parentsSelection );
+            }
+        }
+
+        private void addRoleSearchModal()
+        {
+            final ModalWindow rolesModalWindow;
+            add( rolesModalWindow = new ModalWindow( "parentrolesmodal" ) );
+            final RoleSearchModalPanel roleSearchModalPanel = new RoleSearchModalPanel( rolesModalWindow.getContentId(), rolesModalWindow, isAdmin );
+            rolesModalWindow.setContent( roleSearchModalPanel );
+            rolesModalWindow.setWindowClosedCallback( new ModalWindow.WindowClosedCallback()
+            {
+                @Override
+                public void onClose( AjaxRequestTarget target )
+                {
+                    parentConstraint = roleSearchModalPanel.getRoleSelection();
+                    if ( parentConstraint != null )
+                    {
+                        parentsSelection = parentConstraint.getName();
+                        Role role = (Role)getDefaultModelObject();
+                        role.setParent( parentsSelection );
+                        target.add( parentsCB );
+                        component = editForm;
+                    }
+                }
+            } );
+
+            add( new AjaxButton( GlobalIds.PARENTROLES_SEARCH )
+            {
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
+                {
+                    String msg = "clicked on parent roles search";
+                    msg += parentsSelection != null ? ": " + parentsSelection : "";
+                    roleSearchModalPanel.setRoleSearchVal( parentsSelection );
+                    display.setMessage( msg );
+                    log.debug( msg );
+                    target.prependJavaScript( GlobalIds.WICKET_WINDOW_UNLOAD_CONFIRMATION_FALSE );
+                    rolesModalWindow.show( target );
+                }
+                @Override
+                protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+                {
+                    super.updateAjaxAttributes( attributes );
+                    AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                    {
+                        @Override
+                        public CharSequence getFailureHandler( Component component )
+                        {
+                            return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                        }
+                    };
+                    attributes.getAjaxCallListeners().add( ajaxCallListener );
+                }
+            } );
+
+            String modalLabel;
+            if(isAdmin)
+            {
+                modalLabel = "Admin Role Selection Modal";
+            }
+            else
+            {
+                modalLabel = "RBAC Role Selection Modal";
+            }
+            rolesModalWindow.setTitle( modalLabel );
+            rolesModalWindow.setInitialWidth( 700 );
+            rolesModalWindow.setInitialHeight( 450 );
+            rolesModalWindow.setCookieName( "role-assign-modal" );
+        }
+
+        @Override
+        public void onEvent(final IEvent<?> event)
+        {
+            if (event.getPayload() instanceof SelectModelEvent)
+            {
+                SelectModelEvent modelEvent = (SelectModelEvent) event.getPayload();
+                T role = (T) modelEvent.getEntity();
+                this.setModelObject( role );
+                parentsSelection = "";
+                if(VUtil.isNotNullOrEmpty(((Role)role).getParents()))
+                {
+                    parents = new ArrayList<String>(((Role)role).getParents());
+                    parentsCB = new ComboBox<String>( GlobalIds.PARENTS, new PropertyModel<String>( this, PARENTS_SELECTION ),parents );
+                }
+                else
+                {
+                    parents = new ArrayList<String>();
+                    parentsCB = new ComboBox<String>( GlobalIds.PARENTS, new PropertyModel<String>( this, PARENTS_SELECTION ),parents );
+                }
+                editForm.addOrReplace(parentsCB);
+                String msg = "Role: " + ((Role)role).getName() + " has been selected";
+                log.debug(msg);
+                display.setMessage(msg);
+                component = editForm;
+            }
+            else if (event.getPayload() instanceof AjaxRequestTarget)
+            {
+                // only add the form to ajax target if something has changed...
+                if (component != null)
+                {
+                    AjaxRequestTarget target = ((AjaxRequestTarget) event.getPayload());
+                    log.debug(".onEvent AjaxRequestTarget: " + target.toString());
+                    target.add(component);
+                    component = null;
+                }
+                display.display((AjaxRequestTarget) event.getPayload());
+            }
+        }
+
+        @Override
+        protected void onBeforeRender()
+        {
+            if(getModel() != null)
+            {
+                // push the 'changed' model down into the constraint panel:
+                constraintPanel.setDefaultModel(getModel());
+                if(isAdmin)
+                {
+                    // push the 'changed' model down into the admin role detail panel:
+                    auxPanel.setDefaultModel( getModel() );
+                    AdminRole role = (AdminRole)getModel().getObject();
+                    if(role != null)
+                    {
+                        if(role.getOsP() != null)
+                        {
+                            auxPanel.setPermous( new ArrayList<String>(role.getOsP() ) );
+                        }
+                        else
+                        {
+                            auxPanel.setPermous( new ArrayList<String>( ) );
+                        }
+                        if(role.getOsU() != null)
+                        {
+                            auxPanel.setUserous( new ArrayList<String>(role.getOsU() ) );
+                        }
+                        else
+                        {
+                            auxPanel.setUserous( new ArrayList<String>( ) );
+                        }
+                    }
+                }
+            }
+            else
+            {
+                log.info(".onBeforeRender null model object");
+            }
+            super.onBeforeRender();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-commander/blob/547b9ccd/src/main/java/org/apache/directory/fortress/web/panel/RoleListPanel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/web/panel/RoleListPanel.java b/src/main/java/org/apache/directory/fortress/web/panel/RoleListPanel.java
new file mode 100644
index 0000000..8096b38
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/web/panel/RoleListPanel.java
@@ -0,0 +1,306 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.
+ *
+ */
+
+package org.apache.directory.fortress.web.panel;
+
+import com.inmethod.grid.IGridColumn;
+import com.inmethod.grid.SizeUnit;
+import com.inmethod.grid.column.PropertyColumn;
+import com.inmethod.grid.treegrid.TreeGrid;
+import org.apache.log4j.Logger;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.html.form.FormComponentPanel;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.directory.fortress.web.GlobalIds;
+import org.apache.directory.fortress.web.GlobalUtils;
+import org.apache.directory.fortress.web.RoleListModel;
+import org.apache.directory.fortress.web.SaveModelEvent;
+import org.apache.directory.fortress.web.SecureIndicatingAjaxButton;
+import org.apache.directory.fortress.web.SelectModelEvent;
+import org.apache.directory.fortress.core.rbac.AdminRole;
+import org.apache.directory.fortress.core.rbac.FortEntity;
+import org.apache.directory.fortress.core.rbac.Role;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ *
+ * @author Shawn McKinney
+ * @version $Rev$
+ */
+public class RoleListPanel<T extends Serializable> extends FormComponentPanel
+{
+    private static final Logger log = Logger.getLogger(RoleListPanel.class.getName());
+    private Form listForm;
+    private DefaultTreeModel treeModel;
+    private DefaultMutableTreeNode node;
+    private TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid;
+    private DefaultMutableTreeNode rootNode;
+    private String searchVal;
+    private boolean isAdmin;
+
+    public RoleListPanel(String id, final boolean isAdmin)
+    {
+        super(id);
+        this.isAdmin = isAdmin;
+        RoleListModel roleListModel = new RoleListModel(createRole(""), isAdmin, GlobalUtils.getRbacSession( this ));
+        setDefaultModel(roleListModel);
+        List<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>> columns =
+            new ArrayList<IGridColumn<DefaultTreeModel, DefaultMutableTreeNode, String>>();
+        columns.add(new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+            Model.of("Name"), "userObject.name"));
+
+        PropertyColumn description = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Description"), "userObject.Description");
+        description.setInitialSize(300);
+        columns.add(description);
+
+        PropertyColumn beginDate = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Begin Date"), "userObject.BeginDate");
+        beginDate.setInitialSize(80);
+        columns.add(beginDate);
+
+        PropertyColumn endDate = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("End Date"), "userObject.EndDate");
+        endDate.setInitialSize(80);
+        columns.add(endDate);
+
+        PropertyColumn beginLockDate = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Begin Lock Dt"), "userObject.BeginLockDate");
+        beginLockDate.setInitialSize(80);
+        columns.add(beginLockDate);
+
+        PropertyColumn endLockDate = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("End Lock Dt"), "userObject.EndLockDate");
+        endLockDate.setInitialSize(80);
+        columns.add(endLockDate);
+
+        PropertyColumn beginTime = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Begin Tm"), "userObject.BeginTime");
+        beginTime.setInitialSize(70);
+        columns.add(beginTime);
+
+        PropertyColumn endTime = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("End Tm"), "userObject.EndTime");
+        endTime.setInitialSize(70);
+        columns.add(endTime);
+
+        PropertyColumn dayMask = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("DayMask"), "userObject.DayMask");
+        dayMask.setInitialSize(80);
+        columns.add(dayMask);
+
+        PropertyColumn parents = new PropertyColumn<DefaultTreeModel, DefaultMutableTreeNode, String, String>(
+                    Model.of("Parents"), "userObject.parents");
+        parents.setInitialSize(250);
+        columns.add(parents);
+
+        List<T> roles = (List<T>)getDefaultModel().getObject();
+        treeModel = createTreeModel(roles);
+        grid = new TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String>("roletreegrid", treeModel, columns)
+        {
+            @Override
+            public void selectItem(IModel itemModel, boolean selected)
+            {
+                node = (DefaultMutableTreeNode) itemModel.getObject();
+                if(!node.isRoot())
+                {
+                    T role = (T)node.getUserObject();
+                    if (super.isItemSelected(itemModel))
+                    {
+                        log.debug("TreeGrid.addGrid.selectItem item is selected");
+                        super.selectItem(itemModel, false);
+                    }
+                    else
+                    {
+                        super.selectItem(itemModel, true);
+                        SelectModelEvent.send(getPage(), this, (FortEntity)role);
+                    }
+                }
+            }
+        };
+        grid.setContentHeight(50, SizeUnit.EM);
+        grid.setAllowSelectMultiple(false);
+        grid.setClickRowToSelect(true);
+        grid.setClickRowToDeselect(false);
+        grid.setSelectToEdit(false);
+        // expand the root node
+        grid.getTreeState().expandNode((TreeNode) treeModel.getRoot());
+        this.listForm = new Form("form");
+        this.listForm.add(grid);
+        grid.setOutputMarkupId(true);
+        TextField searchValFld = new TextField(GlobalIds.SEARCH_VAL, new PropertyModel<String>(this, GlobalIds.SEARCH_VAL));
+        this.listForm.add(searchValFld);
+
+        this.listForm.add( new SecureIndicatingAjaxButton( GlobalIds.SEARCH, GlobalIds.REVIEW_MGR, "findRoles" )
+        {
+            @Override
+            protected void onSubmit(AjaxRequestTarget target, Form form)
+            {
+                log.debug(".search onSubmit");
+                info("Searching Roles...");
+                if(!VUtil.isNotNullOrEmpty(searchVal))
+                {
+                    searchVal = "";
+                }
+                T srchRole = createRole(searchVal);
+                setDefaultModel(new RoleListModel(srchRole, isAdmin, GlobalUtils.getRbacSession( this )));
+                treeModel.reload();
+                rootNode.removeAllChildren();
+                List<Role> roles = (List<Role>) getDefaultModelObject();
+                if(VUtil.isNotNullOrEmpty(roles))
+                {
+                    for (T role : (List<T>)roles)
+                        rootNode.add(new DefaultMutableTreeNode(role));
+                    info("Search returned " + roles.size() + " matching objects");
+                }
+                else
+                {
+                    info("No matching objects found");
+                }
+                target.add(grid);
+            }
+
+            @Override
+            public void onError(AjaxRequestTarget target, Form form)
+            {
+                log.warn(".search.onError");
+                target.add();
+            }
+            @Override
+            protected void updateAjaxAttributes( AjaxRequestAttributes attributes )
+            {
+                super.updateAjaxAttributes( attributes );
+                AjaxCallListener ajaxCallListener = new AjaxCallListener()
+                {
+                    @Override
+                    public CharSequence getFailureHandler( Component component )
+                    {
+                        return GlobalIds.WINDOW_LOCATION_REPLACE_COMMANDER_HOME_HTML;
+                    }
+                };
+                attributes.getAjaxCallListeners().add( ajaxCallListener );
+            }
+        });
+        add(this.listForm);
+    }
+
+    @Override
+    public void onEvent(IEvent event)
+    {
+        if (event.getPayload() instanceof SaveModelEvent)
+        {
+            SaveModelEvent modelEvent = (SaveModelEvent) event.getPayload();
+            switch(modelEvent.getOperation())
+            {
+                case ADD:
+                    add(modelEvent.getEntity());
+                    break;
+                case UPDATE:
+                    modelChanged();
+                    break;
+                case DELETE:
+                    prune();
+                    break;
+                default:
+                    break;
+            }
+            AjaxRequestTarget target = ((SaveModelEvent) event.getPayload()).getAjaxRequestTarget();
+            target.add(grid);
+            log.debug(".onEvent SaveModelEvent: " + target.toString());
+        }
+    }
+
+    public void add(FortEntity entity)
+    {
+        if (getDefaultModelObject() != null)
+        {
+             List<Role> roles = ((List<Role>) getDefaultModelObject());
+            roles.add((Role) entity);
+            treeModel.insertNodeInto(new DefaultMutableTreeNode(entity), rootNode, roles.size());
+        }
+    }
+
+    public void prune()
+    {
+        removeSelectedItems(grid);
+    }
+
+    private void removeSelectedItems(TreeGrid<DefaultTreeModel, DefaultMutableTreeNode, String> grid)
+    {
+        Collection<IModel<DefaultMutableTreeNode>> selected = grid.getSelectedItems();
+        for (IModel<DefaultMutableTreeNode> model : selected)
+        {
+            DefaultMutableTreeNode node = model.getObject();
+            treeModel.removeNodeFromParent(node);
+            Role role = (Role) node.getUserObject();
+            log.debug(".removeSelectedItems role node: " + role.getName());
+            List<Role> roles = ((List<Role>) getDefaultModel().getObject());
+            roles.remove(role.getName());
+        }
+    }
+
+    private DefaultTreeModel createTreeModel(List<T> roles)
+    {
+        DefaultTreeModel model;
+        Role root = new Role();
+        //root.setName("Roles");
+        rootNode = new DefaultMutableTreeNode(root);
+        model = new DefaultTreeModel(rootNode);
+        if (roles == null)
+            log.debug("no Roles found");
+        else
+        {
+            log.debug("Roles found:" + roles.size());
+            for (T role : roles)
+                rootNode.add(new DefaultMutableTreeNode(role));
+        }
+        return model;
+    }
+
+    private T createRole(String name)
+    {
+        T role;
+        if(isAdmin)
+        {
+            role = (T)new AdminRole(name);
+        }
+        else
+        {
+            role = (T)new Role(name);
+        }
+        return role;
+    }
+}
\ No newline at end of file