You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2016/04/18 10:05:57 UTC

[5/7] syncope git commit: [SYNCOPE-156, SYNCOPE-817] provides wizard to manage resources and connectors

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java
deleted file mode 100644
index c2f7653..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * 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.syncope.client.console.wizards.provision;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
-import org.apache.commons.collections4.Transformer;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.panels.ProvisionAuxClassesPanel;
-import org.apache.syncope.client.console.panels.ResourceMappingPanel;
-import org.apache.syncope.client.console.rest.AnyTypeRestClient;
-import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
-import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
-import org.apache.syncope.common.lib.EntityTOUtils;
-import org.apache.syncope.common.lib.to.AnyTypeTO;
-import org.apache.syncope.common.lib.to.ProvisionTO;
-import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.wizard.WizardModel;
-import org.apache.wicket.extensions.wizard.WizardStep;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.form.FormComponent;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
-import org.apache.wicket.model.StringResourceModel;
-
-public class ProvisionWizardBuilder extends AjaxWizardBuilder<ProvisionTO> implements Serializable {
-
-    private static final long serialVersionUID = 3739399543837732640L;
-
-    private final ResourceTO resourceTO;
-
-    private final LoadableDetachableModel<List<String>> anyTypes = new LoadableDetachableModel<List<String>>() {
-
-        private static final long serialVersionUID = 5275935387613157437L;
-
-        @Override
-        protected List<String> load() {
-            final List<String> currentlyAdded = new ArrayList<>();
-
-            CollectionUtils.collect(resourceTO.getProvisions(), new Transformer<ProvisionTO, String>() {
-
-                @Override
-                public String transform(final ProvisionTO provisionTO) {
-                    return provisionTO.getAnyType();
-                }
-            }, currentlyAdded);
-
-            final List<String> res = new ArrayList<>();
-
-            CollectionUtils.filter(CollectionUtils.collect(new AnyTypeRestClient().list(),
-                    EntityTOUtils.<String, AnyTypeTO>keyTransformer(), res),
-                    new Predicate<String>() {
-
-                @Override
-                public boolean evaluate(final String key) {
-                    return !currentlyAdded.contains(key);
-                }
-            });
-
-            return res;
-        }
-    };
-
-    /**
-     * The object type specification step.
-     */
-    private final class ObjectType extends WizardStep {
-
-        private static final long serialVersionUID = -1657800545799468278L;
-
-        private static final String ACCOUNT = "__ACCOUNT__";
-
-        private static final String GROUP = "__GROUP__";
-
-        ObjectType(final ProvisionTO item) {
-            super(new ResourceModel("type.title", StringUtils.EMPTY),
-                    new ResourceModel("type.summary", StringUtils.EMPTY), new Model<>(item));
-
-            final WebMarkupContainer container = new WebMarkupContainer("container");
-            container.setOutputMarkupId(true);
-            add(container);
-
-            final FieldPanel<String> type = new AjaxDropDownChoicePanel<>(
-                    "type", "type", new PropertyModel<String>(item, "anyType"), false).
-                    setChoices(anyTypes).
-                    setStyleSheet("form-control").
-                    setRequired(true);
-            container.add(type);
-
-            final FormComponent<String> clazz = new TextField<>(
-                    "class", new PropertyModel<String>(item, "objectClass")).setRequired(true);
-            container.add(clazz);
-
-            type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                private static final long serialVersionUID = -1107858522700306810L;
-
-                @Override
-                protected void onUpdate(final AjaxRequestTarget target) {
-                    if (AnyTypeKind.USER.name().equals(type.getModelObject())) {
-                        clazz.setModelObject(ACCOUNT);
-                        target.add(container);
-                    } else if (AnyTypeKind.GROUP.name().equals(type.getModelObject())) {
-                        clazz.setModelObject(GROUP);
-                        target.add(container);
-                    }
-                }
-            });
-        }
-    }
-
-    /**
-     * AuxClasses definition step.
-     */
-    private final class AuxClasses extends WizardStep {
-
-        private static final long serialVersionUID = 5315236191866427500L;
-
-        AuxClasses(final ProvisionTO item) {
-            setTitleModel(new ResourceModel("auxClasses.title"));
-            setSummaryModel(new StringResourceModel("auxClasses.summary", this, new Model<>(item)));
-
-            add(new ProvisionAuxClassesPanel("auxClasses", item));
-        }
-    }
-
-    /**
-     * Mapping definition step.
-     */
-    private final class Mapping extends WizardStep {
-
-        private static final long serialVersionUID = 3454904947720856253L;
-
-        Mapping(final ProvisionTO item) {
-            setTitleModel(new ResourceModel("mapping.title"));
-            setSummaryModel(new StringResourceModel("mapping.summary", this, new Model<>(item)));
-
-            add(new ResourceMappingPanel("mapping", resourceTO, item));
-        }
-    }
-
-    /**
-     * AccountLink specification step.
-     */
-    private final class ConnObjectLink extends WizardStep {
-
-        private static final long serialVersionUID = 2359955465172450478L;
-
-        ConnObjectLink(final ProvisionTO item) {
-            super(new ResourceModel("link.title", StringUtils.EMPTY),
-                    new ResourceModel("link.summary", StringUtils.EMPTY));
-
-            final WebMarkupContainer connObjectLinkContainer = new WebMarkupContainer("connObjectLinkContainer");
-            connObjectLinkContainer.setOutputMarkupId(true);
-            add(connObjectLinkContainer);
-
-            boolean connObjectLinkEnabled = false;
-            if (StringUtils.isNotBlank(item.getMapping().getConnObjectLink())) {
-                connObjectLinkEnabled = true;
-            }
-
-            final AjaxCheckBoxPanel connObjectLinkCheckbox = new AjaxCheckBoxPanel(
-                    "connObjectLinkCheckbox",
-                    new ResourceModel("connObjectLinkCheckbox", "connObjectLinkCheckbox").getObject(),
-                    new Model<>(connObjectLinkEnabled),
-                    false);
-            connObjectLinkCheckbox.setEnabled(true);
-
-            connObjectLinkContainer.add(connObjectLinkCheckbox);
-
-            final AjaxTextFieldPanel connObjectLink = new AjaxTextFieldPanel(
-                    "connObjectLink",
-                    new ResourceModel("connObjectLink", "connObjectLink").getObject(),
-                    new PropertyModel<String>(item.getMapping(), "connObjectLink"),
-                    false);
-            connObjectLink.setEnabled(connObjectLinkEnabled);
-            connObjectLinkContainer.add(connObjectLink);
-
-            connObjectLinkCheckbox.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                private static final long serialVersionUID = -1107858522700306810L;
-
-                @Override
-                protected void onUpdate(final AjaxRequestTarget target) {
-                    if (connObjectLinkCheckbox.getModelObject()) {
-                        connObjectLink.setEnabled(Boolean.TRUE);
-                        connObjectLink.setModelObject("");
-                    } else {
-                        connObjectLink.setEnabled(Boolean.FALSE);
-                        connObjectLink.setModelObject("");
-                    }
-
-                    target.add(connObjectLink);
-                }
-            });
-        }
-    }
-
-    /**
-     * Construct.
-     *
-     * @param resurceTO external resource to be updated.
-     * @param pageRef Caller page reference.
-     */
-    public ProvisionWizardBuilder(final ResourceTO resurceTO, final PageReference pageRef) {
-        super(new ProvisionTO(), pageRef);
-        this.resourceTO = resurceTO;
-    }
-
-    @Override
-    protected WizardModel buildModelSteps(final ProvisionTO modelObject, final WizardModel wizardModel) {
-        wizardModel.add(new ObjectType(modelObject));
-        wizardModel.add(new AuxClasses(modelObject));
-        wizardModel.add(new Mapping(modelObject));
-        wizardModel.add(new ConnObjectLink(modelObject));
-        return wizardModel;
-    }
-
-    @Override
-    protected Serializable onApplyInternal(final ProvisionTO modelObject) {
-        return modelObject;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractConnConfPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractConnConfPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractConnConfPanel.java
new file mode 100644
index 0000000..78d1066
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractConnConfPanel.java
@@ -0,0 +1,73 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.List;
+import org.apache.syncope.client.console.wicket.markup.html.list.ConnConfPropertyListView;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+
+public abstract class AbstractConnConfPanel<T extends AbstractBaseBean> extends WizardStep {
+
+    private static final long serialVersionUID = -2025535531121434050L;
+
+    protected final WebMarkupContainer propertiesContainer;
+
+    protected final AjaxButton check;
+
+    protected final T modelObject;
+
+    public AbstractConnConfPanel(final T model) {
+        super();
+        this.modelObject = model;
+        setOutputMarkupId(true);
+
+        propertiesContainer = new WebMarkupContainer("connectorPropertiesContainer");
+        propertiesContainer.setOutputMarkupId(true);
+        add(propertiesContainer);
+
+        check = new IndicatingAjaxButton("check", new ResourceModel("check")) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                check(target);
+            }
+        };
+        propertiesContainer.add(check);
+    }
+
+    protected void setConfPropertyListView(final IModel<List<ConnConfProperty>> model, final boolean withOverridable) {
+        propertiesContainer.add(new ConnConfPropertyListView(
+                "connectorProperties", model, withOverridable).setOutputMarkupId(true));
+    }
+
+    protected abstract void check(final AjaxRequestTarget taget);
+
+    protected abstract List<ConnConfProperty> getConnProperties(final T instance);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java
new file mode 100644
index 0000000..bdd6caf
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractResourceWizardBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.io.Serializable;
+import org.apache.syncope.client.console.topology.TopologyNode;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal.ModalEvent;
+import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+/**
+ * Modal window with Resource form.
+ *
+ * @param <T>
+ */
+public abstract class AbstractResourceWizardBuilder<T extends Serializable> extends AjaxWizardBuilder<Serializable> {
+
+    private static final long serialVersionUID = 1734415311027284221L;
+
+    public AbstractResourceWizardBuilder(final T modelObject, final PageReference pageRef) {
+        super(modelObject, pageRef);
+    }
+
+    public static class CreateEvent extends ModalEvent {
+
+        private static final long serialVersionUID = -4488921035707289039L;
+
+        private final Serializable key;
+
+        private final String displayName;
+
+        private final Serializable parent;
+
+        private final TopologyNode.Kind kind;
+
+        public CreateEvent(
+                final Serializable key,
+                final String displayName,
+                final TopologyNode.Kind kind,
+                final Serializable parent,
+                final AjaxRequestTarget target) {
+            super(target);
+            this.key = key;
+            this.displayName = displayName;
+            this.kind = kind;
+            this.parent = parent;
+        }
+
+        public Serializable getKey() {
+            return key;
+        }
+
+        public String getDisplayName() {
+            return displayName;
+        }
+
+        public TopologyNode.Kind getKind() {
+            return kind;
+        }
+
+        public Serializable getParent() {
+            return parent;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java
new file mode 100644
index 0000000..9dad020
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/CapabilitiesPanel.java
@@ -0,0 +1,43 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.util.ListModel;
+
+public class CapabilitiesPanel extends Panel {
+
+    private static final long serialVersionUID = -2025535531121434050L;
+
+    public CapabilitiesPanel(final PropertyModel<List<ConnectorCapability>> model) {
+        super("capabilities");
+        setOutputMarkupId(true);
+
+        AjaxPalettePanel<ConnectorCapability> capabilitiesPalette = new AjaxPalettePanel.Builder<ConnectorCapability>().
+                setAllowMoveAll(true).
+                build("capabilities", model, new ListModel<>(Arrays.asList(ConnectorCapability.values())));
+        capabilitiesPalette.setOutputMarkupId(true);
+        add(capabilitiesPalette);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnCapabilitiesPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnCapabilitiesPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnCapabilitiesPanel.java
new file mode 100644
index 0000000..d82fb95
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnCapabilitiesPanel.java
@@ -0,0 +1,35 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.model.PropertyModel;
+
+public class ConnCapabilitiesPanel extends WizardStep {
+
+    private static final long serialVersionUID = -2025535531121434050L;
+
+    public ConnCapabilitiesPanel(final PropertyModel<List<ConnectorCapability>> model) {
+        super();
+        setOutputMarkupId(true);
+        add(new CapabilitiesPanel(model));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorConfPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorConfPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorConfPanel.java
new file mode 100644
index 0000000..722ddfa
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorConfPanel.java
@@ -0,0 +1,117 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.common.lib.to.ConnBundleTO;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.types.ConnConfPropSchema;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+
+public abstract class ConnectorConfPanel extends AbstractConnConfPanel<ConnInstanceTO> {
+
+    private static final long serialVersionUID = -2025535531121434050L;
+
+    private final List<ConnBundleTO> bundles;
+
+    public ConnectorConfPanel(final ConnInstanceTO connInstanceTO, final List<ConnBundleTO> bundles) {
+        super(connInstanceTO);
+        this.bundles = bundles;
+
+        LoadableDetachableModel<List<ConnConfProperty>> model = new LoadableDetachableModel<List<ConnConfProperty>>() {
+
+            private static final long serialVersionUID = -2965284931860212687L;
+
+            @Override
+            protected List<ConnConfProperty> load() {
+                List<ConnConfProperty> properties = getConnProperties(connInstanceTO);
+                connInstanceTO.getConf().clear();
+                connInstanceTO.getConf().addAll(properties);
+
+                return new PropertyModel<List<ConnConfProperty>>(modelObject, "conf") {
+
+                    private static final long serialVersionUID = -7809699384012595307L;
+
+                    @Override
+                    public List<ConnConfProperty> getObject() {
+                        final List<ConnConfProperty> res = new ArrayList<>((Set<ConnConfProperty>) super.getObject());
+
+                        // re-order properties
+                        Collections.sort(res, new Comparator<ConnConfProperty>() {
+
+                            @Override
+                            public int compare(final ConnConfProperty left, final ConnConfProperty right) {
+                                if (left == null) {
+                                    return -1;
+                                } else {
+                                    return left.compareTo(right);
+                                }
+                            }
+                        });
+
+                        return res;
+                    }
+                }.getObject();
+            }
+        };
+
+        setConfPropertyListView(model, true);
+    }
+
+    /**
+     * Get available configuration properties.
+     *
+     * @param instance connector instance.
+     * @return configuration properties.
+     */
+    @Override
+    protected final List<ConnConfProperty> getConnProperties(final ConnInstanceTO instance) {
+        return CollectionUtils.collect(
+                ConnectorWizardBuilder.getBundle(instance, bundles).getProperties(),
+                new Transformer<ConnConfPropSchema, ConnConfProperty>() {
+
+            @Override
+            public ConnConfProperty transform(final ConnConfPropSchema key) {
+                final ConnConfProperty property = new ConnConfProperty();
+                property.setSchema(key);
+
+                if (instance.getKey() != null
+                        && instance.getConfMap().containsKey(key.getName())
+                        && instance.getConfMap().get(key.getName()).getValues() != null) {
+
+                    property.getValues().addAll(instance.getConfMap().get(key.getName()).getValues());
+                    property.setOverridable(instance.getConfMap().get(key.getName()).isOverridable());
+                }
+
+                if (property.getValues().isEmpty() && !key.getDefaultValues().isEmpty()) {
+                    property.getValues().addAll(key.getDefaultValues());
+                }
+                return property;
+            }
+        }, new ArrayList<ConnConfProperty>());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
new file mode 100644
index 0000000..28fda4a
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorDetailsPanel.java
@@ -0,0 +1,155 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.to.ConnBundleTO;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.ConnPoolConfTO;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.model.PropertyModel;
+
+public class ConnectorDetailsPanel extends WizardStep {
+
+    private static final long serialVersionUID = -2435937897614232137L;
+
+    public ConnectorDetailsPanel(final ConnInstanceTO connInstanceTO, final List<ConnBundleTO> bundles) {
+
+        super();
+        setOutputMarkupId(true);
+
+        AjaxTextFieldPanel displayName = new AjaxTextFieldPanel(
+                "displayName", "displayName", new PropertyModel<String>(connInstanceTO, "displayName"), false);
+        displayName.setOutputMarkupId(true);
+        displayName.addRequiredLabel();
+        add(displayName);
+
+        AjaxTextFieldPanel location = new AjaxTextFieldPanel(
+                "location", "location", new PropertyModel<String>(connInstanceTO, "location"), false);
+        location.addRequiredLabel();
+        location.setOutputMarkupId(true);
+        location.setEnabled(false);
+        add(location);
+
+        final AjaxDropDownChoicePanel<String> bundleName = new AjaxDropDownChoicePanel<>(
+                "bundleName",
+                "bundleName",
+                new PropertyModel<String>(connInstanceTO, "bundleName"), false);
+        ((DropDownChoice<String>) bundleName.getField()).setNullValid(true);
+        bundleName.setChoices(CollectionUtils.collect(bundles, new Transformer<ConnBundleTO, String>() {
+
+            @Override
+            public String transform(final ConnBundleTO input) {
+                return input.getBundleName();
+            }
+        }, new ArrayList<String>()));
+        bundleName.addRequiredLabel();
+        bundleName.setOutputMarkupId(true);
+        bundleName.setEnabled(connInstanceTO.getKey() == null || connInstanceTO.getKey() == 0);
+        bundleName.getField().setOutputMarkupId(true);
+        add(bundleName);
+
+        final AjaxDropDownChoicePanel<String> version = new AjaxDropDownChoicePanel<>(
+                "version", "version", new PropertyModel<String>(connInstanceTO, "version"), false);
+        version.setChoices(getVersions(connInstanceTO, bundles));
+        version.addRequiredLabel();
+        version.setEnabled(connInstanceTO.getBundleName() != null);
+        version.setOutputMarkupId(true);
+        version.getField().setOutputMarkupId(true);
+        add(version);
+
+        bundleName.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                ((DropDownChoice<String>) bundleName.getField()).setNullValid(false);
+                version.setEnabled(true);
+
+                List<String> versions = getVersions(connInstanceTO, bundles);
+                if (versions.size() == 1) {
+                    connInstanceTO.setVersion(versions.get(0));
+                    version.getField().setModelObject(versions.get(0));
+                }
+                version.setChoices(versions);
+
+                target.add(version);
+            }
+        });
+
+        if (connInstanceTO.getPoolConf() == null) {
+            connInstanceTO.setPoolConf(new ConnPoolConfTO());
+        }
+
+        add(new AjaxSpinnerFieldPanel.Builder<Integer>().min(0).max(Integer.MAX_VALUE).build(
+                "connRequestTimeout", "connRequestTimeout", Integer.class,
+                new PropertyModel<Integer>(connInstanceTO, "connRequestTimeout")));
+
+        add(new AjaxSpinnerFieldPanel.Builder<Integer>().min(0).max(Integer.MAX_VALUE).build(
+                "poolMaxObjects", "poolMaxObjects", Integer.class,
+                new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxObjects")));
+
+        add(new AjaxSpinnerFieldPanel.Builder<Integer>().min(0).max(Integer.MAX_VALUE).build(
+                "poolMinIdle", "poolMinIdle", Integer.class,
+                new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "minIdle")));
+
+        add(new AjaxSpinnerFieldPanel.Builder<Integer>().min(0).max(Integer.MAX_VALUE).build(
+                "poolMaxIdle", "poolMaxIdle", Integer.class,
+                new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxIdle")));
+
+        add(new AjaxSpinnerFieldPanel.Builder<Long>().min(0L).max(Long.MAX_VALUE).build(
+                "poolMaxWait", "poolMaxWait", Long.class,
+                new PropertyModel<Long>(connInstanceTO.getPoolConf(), "maxWait")));
+
+        add(new AjaxSpinnerFieldPanel.Builder<Long>().min(0L).max(Long.MAX_VALUE).build(
+                "poolMinEvictableIdleTime", "poolMinEvictableIdleTime", Long.class,
+                new PropertyModel<Long>(connInstanceTO.getPoolConf(), "minEvictableIdleTimeMillis")));
+    }
+
+    private List<String> getVersions(final ConnInstanceTO connInstanceTO, final List<ConnBundleTO> bundles) {
+        return new ArrayList<>(CollectionUtils.collect(
+                CollectionUtils.select(bundles, new Predicate<ConnBundleTO>() {
+
+                    @Override
+                    public boolean evaluate(final ConnBundleTO object) {
+                        return object.getLocation().equals(connInstanceTO.getLocation())
+                                && object.getBundleName().equals(connInstanceTO.getBundleName());
+                    }
+                }), new Transformer<ConnBundleTO, String>() {
+
+            @Override
+            public String transform(final ConnBundleTO input) {
+                return input.getVersion();
+            }
+        }, new HashSet<String>()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java
new file mode 100644
index 0000000..4c41f6c
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ConnectorWizardBuilder.java
@@ -0,0 +1,145 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.io.Serializable;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.ConnectorRestClient;
+import org.apache.syncope.client.console.topology.TopologyNode;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.to.ConnBundleTO;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.model.PropertyModel;
+
+/**
+ * Modal window with Connector form.
+ */
+public class ConnectorWizardBuilder extends AbstractResourceWizardBuilder<ConnInstanceTO> {
+
+    private static final long serialVersionUID = -2025535531121434050L;
+
+    private final ConnectorRestClient connectorRestClient = new ConnectorRestClient();
+
+    private final List<ConnBundleTO> bundles;
+
+    public ConnectorWizardBuilder(final ConnInstanceTO defaultItem, final PageReference pageRef) {
+        super(defaultItem, pageRef);
+        this.bundles = CollectionUtils.select(connectorRestClient.getAllBundles(), new Predicate<ConnBundleTO>() {
+
+            @Override
+            public boolean evaluate(final ConnBundleTO object) {
+                return object.getLocation().equals(defaultItem.getLocation());
+            }
+        }, new ArrayList<ConnBundleTO>());
+    }
+
+    @Override
+    protected WizardModel buildModelSteps(final Serializable modelObject, final WizardModel wizardModel) {
+        final ConnInstanceTO connInstanceTO = ConnInstanceTO.class.cast(modelObject);
+        wizardModel.add(new ConnectorDetailsPanel(connInstanceTO, bundles));
+        wizardModel.add(new ConnectorConfPanel(connInstanceTO, bundles) {
+
+            private static final long serialVersionUID = -5886691077681158494L;
+
+            @Override
+            protected void check(final AjaxRequestTarget target) {
+                if (connectorRestClient.check(modelObject)) {
+                    info(getString(Constants.OPERATION_SUCCEEDED));
+                } else {
+                    error(getString("error_connection"));
+                }
+                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+            }
+
+            @Override
+            protected void onComponentTag(final ComponentTag tag) {
+                tag.append("class", "scrollable-tab-content", " ");
+            }
+
+        });
+        wizardModel.add(new ConnCapabilitiesPanel(
+                new PropertyModel<List<ConnectorCapability>>(connInstanceTO, "capabilities")));
+        return wizardModel;
+    }
+
+    @Override
+    protected Serializable onApplyInternal(final Serializable modelObject) {
+        final ConnInstanceTO connInstanceTO = ConnInstanceTO.class.cast(modelObject);
+        final ConnBundleTO bundleTO = ConnectorWizardBuilder.getBundle(connInstanceTO, bundles);
+
+        connInstanceTO.setConnectorName(bundleTO.getConnectorName());
+        connInstanceTO.setBundleName(bundleTO.getBundleName());
+        connInstanceTO.setVersion(bundleTO.getVersion());
+
+        // Reset pool configuration if all fields are null
+        if (connInstanceTO.getPoolConf() != null
+                && connInstanceTO.getPoolConf().getMaxIdle() == null
+                && connInstanceTO.getPoolConf().getMaxObjects() == null
+                && connInstanceTO.getPoolConf().getMaxWait() == null
+                && connInstanceTO.getPoolConf().getMinEvictableIdleTimeMillis() == null
+                && connInstanceTO.getPoolConf().getMinIdle() == null) {
+
+            connInstanceTO.setPoolConf(null);
+        }
+
+        final ConnInstanceTO res;
+        if (mode == AjaxWizard.Mode.CREATE) {
+            res = connectorRestClient.create(connInstanceTO);
+        } else {
+            connectorRestClient.update(connInstanceTO);
+            res = connInstanceTO;
+        }
+
+        return res;
+    }
+
+    @Override
+    protected Serializable getCreateCustomPayloadEvent(final Serializable afterObject, final AjaxRequestTarget target) {
+        final ConnInstanceTO actual = ConnInstanceTO.class.cast(afterObject);
+        return new CreateEvent(
+                actual.getKey(),
+                actual.getDisplayName(),
+                TopologyNode.Kind.CONNECTOR,
+                URI.create(actual.getLocation()).toASCIIString(),
+                target);
+    }
+
+    protected static ConnBundleTO getBundle(final ConnInstanceTO connInstanceTO, final List<ConnBundleTO> bundles) {
+        return IterableUtils.find(bundles, new Predicate<ConnBundleTO>() {
+
+            @Override
+            public boolean evaluate(final ConnBundleTO bundle) {
+                return bundle.getBundleName().equals(connInstanceTO.getBundleName())
+                        && bundle.getVersion().equals(connInstanceTO.getVersion());
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
new file mode 100644
index 0000000..87963db
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
@@ -0,0 +1,252 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.ProvisionAuxClassesPanel;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
+import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+
+public class ProvisionWizardBuilder extends AjaxWizardBuilder<ProvisionTO> implements Serializable {
+
+    private static final long serialVersionUID = 3739399543837732640L;
+
+    private final ResourceTO resourceTO;
+
+    private final LoadableDetachableModel<List<String>> anyTypes = new LoadableDetachableModel<List<String>>() {
+
+        private static final long serialVersionUID = 5275935387613157437L;
+
+        @Override
+        protected List<String> load() {
+            final List<String> currentlyAdded = new ArrayList<>();
+
+            CollectionUtils.collect(resourceTO.getProvisions(), new Transformer<ProvisionTO, String>() {
+
+                @Override
+                public String transform(final ProvisionTO provisionTO) {
+                    return provisionTO.getAnyType();
+                }
+            }, currentlyAdded);
+
+            final List<String> res = new ArrayList<>();
+
+            CollectionUtils.filter(CollectionUtils.collect(new AnyTypeRestClient().list(),
+                    EntityTOUtils.<String, AnyTypeTO>keyTransformer(), res),
+                    new Predicate<String>() {
+
+                @Override
+                public boolean evaluate(final String key) {
+                    return !currentlyAdded.contains(key);
+                }
+            });
+
+            return res;
+        }
+    };
+
+    /**
+     * The object type specification step.
+     */
+    private final class ObjectType extends WizardStep {
+
+        private static final long serialVersionUID = -1657800545799468278L;
+
+        private static final String ACCOUNT = "__ACCOUNT__";
+
+        private static final String GROUP = "__GROUP__";
+
+        ObjectType(final ProvisionTO item) {
+            super(new ResourceModel("type.title", StringUtils.EMPTY),
+                    new ResourceModel("type.summary", StringUtils.EMPTY), new Model<>(item));
+
+            final WebMarkupContainer container = new WebMarkupContainer("container");
+            container.setOutputMarkupId(true);
+            add(container);
+
+            final FieldPanel<String> type = new AjaxDropDownChoicePanel<>(
+                    "type", "type", new PropertyModel<String>(item, "anyType"), false).
+                    setChoices(anyTypes).
+                    setStyleSheet("form-control").
+                    setRequired(true);
+            container.add(type);
+
+            final FormComponent<String> clazz = new TextField<>(
+                    "class", new PropertyModel<String>(item, "objectClass")).setRequired(true);
+            container.add(clazz);
+
+            type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    if (AnyTypeKind.USER.name().equals(type.getModelObject())) {
+                        clazz.setModelObject(ACCOUNT);
+                        target.add(container);
+                    } else if (AnyTypeKind.GROUP.name().equals(type.getModelObject())) {
+                        clazz.setModelObject(GROUP);
+                        target.add(container);
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * AuxClasses definition step.
+     */
+    private final class AuxClasses extends WizardStep {
+
+        private static final long serialVersionUID = 5315236191866427500L;
+
+        AuxClasses(final ProvisionTO item) {
+            setTitleModel(new ResourceModel("auxClasses.title"));
+            setSummaryModel(new StringResourceModel("auxClasses.summary", this, new Model<>(item)));
+
+            add(new ProvisionAuxClassesPanel("auxClasses", item));
+        }
+    }
+
+    /**
+     * Mapping definition step.
+     */
+    private final class Mapping extends WizardStep {
+
+        private static final long serialVersionUID = 3454904947720856253L;
+
+        Mapping(final ProvisionTO item) {
+            setTitleModel(new ResourceModel("mapping.title"));
+            setSummaryModel(new StringResourceModel("mapping.summary", this, new Model<>(item)));
+
+            add(new ResourceMappingPanel("mapping", resourceTO, item));
+        }
+    }
+
+    /**
+     * AccountLink specification step.
+     */
+    private final class ConnObjectLink extends WizardStep {
+
+        private static final long serialVersionUID = 2359955465172450478L;
+
+        ConnObjectLink(final ProvisionTO item) {
+            super(new ResourceModel("link.title", StringUtils.EMPTY),
+                    new ResourceModel("link.summary", StringUtils.EMPTY));
+
+            final WebMarkupContainer connObjectLinkContainer = new WebMarkupContainer("connObjectLinkContainer");
+            connObjectLinkContainer.setOutputMarkupId(true);
+            add(connObjectLinkContainer);
+
+            boolean connObjectLinkEnabled = false;
+            if (StringUtils.isNotBlank(item.getMapping().getConnObjectLink())) {
+                connObjectLinkEnabled = true;
+            }
+
+            final AjaxCheckBoxPanel connObjectLinkCheckbox = new AjaxCheckBoxPanel(
+                    "connObjectLinkCheckbox",
+                    new ResourceModel("connObjectLinkCheckbox", "connObjectLinkCheckbox").getObject(),
+                    new Model<>(connObjectLinkEnabled),
+                    false);
+            connObjectLinkCheckbox.setEnabled(true);
+
+            connObjectLinkContainer.add(connObjectLinkCheckbox);
+
+            final AjaxTextFieldPanel connObjectLink = new AjaxTextFieldPanel(
+                    "connObjectLink",
+                    new ResourceModel("connObjectLink", "connObjectLink").getObject(),
+                    new PropertyModel<String>(item.getMapping(), "connObjectLink"),
+                    false);
+            connObjectLink.setEnabled(connObjectLinkEnabled);
+            connObjectLinkContainer.add(connObjectLink);
+
+            connObjectLinkCheckbox.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    if (connObjectLinkCheckbox.getModelObject()) {
+                        connObjectLink.setEnabled(Boolean.TRUE);
+                        connObjectLink.setModelObject("");
+                    } else {
+                        connObjectLink.setEnabled(Boolean.FALSE);
+                        connObjectLink.setModelObject("");
+                    }
+
+                    target.add(connObjectLink);
+                }
+            });
+        }
+    }
+
+    /**
+     * Construct.
+     *
+     * @param resurceTO external resource to be updated.
+     * @param pageRef Caller page reference.
+     */
+    public ProvisionWizardBuilder(final ResourceTO resurceTO, final PageReference pageRef) {
+        super(new ProvisionTO(), pageRef);
+        this.resourceTO = resurceTO;
+    }
+
+    @Override
+    protected WizardModel buildModelSteps(final ProvisionTO modelObject, final WizardModel wizardModel) {
+        wizardModel.add(new ObjectType(modelObject));
+        wizardModel.add(new AuxClasses(modelObject));
+        wizardModel.add(new Mapping(modelObject));
+        wizardModel.add(new ConnObjectLink(modelObject));
+        return wizardModel;
+    }
+
+    @Override
+    protected Serializable onApplyInternal(final ProvisionTO modelObject) {
+        return modelObject;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java
new file mode 100644
index 0000000..5f6073b
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnCapabilitiesPanel.java
@@ -0,0 +1,68 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class ResourceConnCapabilitiesPanel extends WizardStep {
+
+    private static final long serialVersionUID = -114632577031611754L;
+
+    public ResourceConnCapabilitiesPanel(
+            final ResourceTO resourceTO, final Set<ConnectorCapability> connectorCapabilities) {
+        super();
+        setOutputMarkupId(true);
+
+        if (!resourceTO.isOverrideCapabilities() && resourceTO.getCapabilitiesOverride().isEmpty()) {
+            resourceTO.getCapabilitiesOverride().addAll(connectorCapabilities);
+        }
+
+        final CapabilitiesPanel connCapabilitiesPanel = new CapabilitiesPanel(
+                new PropertyModel<List<ConnectorCapability>>(resourceTO, "capabilitiesOverride"));
+        connCapabilitiesPanel.setEnabled(resourceTO.isOverrideCapabilities());
+        add(connCapabilitiesPanel);
+
+        final AjaxCheckBoxPanel overrideCapabilities = new AjaxCheckBoxPanel(
+                "overrideCapabilities",
+                new ResourceModel("overrideCapabilities", "overrideCapabilities").getObject(),
+                new PropertyModel<Boolean>(resourceTO, "overrideCapabilities"));
+        overrideCapabilities.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                connCapabilitiesPanel.setEnabled(overrideCapabilities.getField().getModelObject());
+                target.add(ResourceConnCapabilitiesPanel.this);
+            }
+        });
+        add(overrideCapabilities);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnConfPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnConfPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnConfPanel.java
new file mode 100644
index 0000000..b8be9a6
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceConnConfPanel.java
@@ -0,0 +1,123 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.syncope.client.console.rest.ConnectorRestClient;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+
+public abstract class ResourceConnConfPanel extends AbstractConnConfPanel<ResourceTO> {
+
+    private static final long serialVersionUID = -7982691107029848579L;
+
+    private final ConnectorRestClient restClient = new ConnectorRestClient();
+
+    private final boolean createFlag;
+
+    public ResourceConnConfPanel(final ResourceTO resourceTO, final boolean createFlag) {
+        super(resourceTO);
+        this.createFlag = createFlag;
+
+        LoadableDetachableModel<List<ConnConfProperty>> model = new LoadableDetachableModel<List<ConnConfProperty>>() {
+
+            private static final long serialVersionUID = -2965284931860212687L;
+
+            @Override
+            protected List<ConnConfProperty> load() {
+                final List<ConnConfProperty> confOverride = getConnProperties(resourceTO);
+                resourceTO.getConfOverride().clear();
+                resourceTO.getConfOverride().addAll(confOverride);
+
+                return new PropertyModel<List<ConnConfProperty>>(modelObject, "confOverride") {
+
+                    private static final long serialVersionUID = -7809699384012595307L;
+
+                    @Override
+                    public List<ConnConfProperty> getObject() {
+                        final List<ConnConfProperty> res = new ArrayList<>((Set<ConnConfProperty>) super.getObject());
+
+                        // re-order properties
+                        Collections.sort(res, new Comparator<ConnConfProperty>() {
+
+                            @Override
+                            public int compare(final ConnConfProperty left, final ConnConfProperty right) {
+                                if (left == null) {
+                                    return -1;
+                                } else {
+                                    return left.compareTo(right);
+                                }
+                            }
+                        });
+
+                        return res;
+                    }
+                }.getObject();
+            }
+        };
+
+        setConfPropertyListView(model, true);
+
+        check.setEnabled(!model.getObject().isEmpty());
+        check.setVisible(!model.getObject().isEmpty());
+    }
+
+    /**
+     * Get overridable properties.
+     *
+     * @param resourceTO resource instance.
+     * @return overridable properties.
+     */
+    @Override
+    protected final List<ConnConfProperty> getConnProperties(final ResourceTO resourceTO) {
+        List<ConnConfProperty> props = new ArrayList<>();
+
+        if (resourceTO.getConnector() != null && resourceTO.getConnector() > 0) {
+            for (ConnConfProperty property : restClient.read(resourceTO.getConnector()).getConf()) {
+                if (property.isOverridable()) {
+                    props.add(property);
+                }
+            }
+        }
+        if (createFlag || resourceTO.getConfOverride().isEmpty()) {
+            resourceTO.getConfOverride().clear();
+        } else {
+            Map<String, ConnConfProperty> valuedProps = new HashMap<>();
+            for (ConnConfProperty prop : resourceTO.getConfOverride()) {
+                valuedProps.put(prop.getSchema().getName(), prop);
+            }
+
+            for (int i = 0; i < props.size(); i++) {
+                if (valuedProps.containsKey(props.get(i).getSchema().getName())) {
+                    props.set(i, valuedProps.get(props.get(i).getSchema().getName()));
+                }
+            }
+        }
+
+        return props;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1735c44c/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
new file mode 100644
index 0000000..7435a30
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
@@ -0,0 +1,130 @@
+/*
+ * 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.syncope.client.console.wizards.resources;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxSpinnerFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.util.ListModel;
+
+public class ResourceDetailsPanel extends WizardStep {
+
+    private static final long serialVersionUID = -7982691107029848579L;
+
+    private final IModel<List<String>> propagationActionsClasses = new LoadableDetachableModel<List<String>>() {
+
+        private static final long serialVersionUID = 5275935387613157437L;
+
+        @Override
+        protected List<String> load() {
+            return new ArrayList<>(SyncopeConsoleSession.get().getPlatformInfo().getPropagationActions());
+        }
+    };
+
+    public ResourceDetailsPanel(final ResourceTO resourceTO, final boolean createFlag) {
+
+        super();
+        setOutputMarkupId(true);
+
+        final WebMarkupContainer container = new WebMarkupContainer("container");
+        container.setOutputMarkupId(true);
+        container.setRenderBodyOnly(true);
+        add(container);
+
+        container.add(new AjaxTextFieldPanel(
+                "name",
+                new ResourceModel("name", "name").
+                getObject(),
+                new PropertyModel<String>(resourceTO, "key"),
+                false).addRequiredLabel().setEnabled(createFlag));
+
+        container.add(new AjaxCheckBoxPanel(
+                "enforceMandatoryCondition",
+                new ResourceModel("enforceMandatoryCondition", "enforceMandatoryCondition").getObject(),
+                new PropertyModel<Boolean>(resourceTO, "enforceMandatoryCondition"),
+                false));
+
+        container.add(new AjaxSpinnerFieldPanel.Builder<Integer>().build(
+                "propagationPriority",
+                "propagationPriority",
+                Integer.class,
+                new PropertyModel<Integer>(resourceTO, "propagationPriority")));
+
+        container.add(new AjaxCheckBoxPanel("randomPwdIfNotProvided",
+                new ResourceModel("randomPwdIfNotProvided", "randomPwdIfNotProvided").getObject(),
+                new PropertyModel<Boolean>(resourceTO, "randomPwdIfNotProvided"),
+                false));
+
+        container.add(new AjaxPalettePanel.Builder<String>().
+                setAllowMoveAll(true).setAllowOrder(true).
+                build("propagationActionsClassNames",
+                        new PropertyModel<List<String>>(resourceTO, "propagationActionsClassNames"),
+                        new ListModel<>(propagationActionsClasses.getObject())).
+                setOutputMarkupId(true));
+
+        container.add(new AjaxDropDownChoicePanel<>(
+                "createTraceLevel",
+                new ResourceModel("createTraceLevel", "createTraceLevel").getObject(),
+                new PropertyModel<TraceLevel>(resourceTO, "createTraceLevel"),
+                false).
+                setChoices(Arrays.asList(TraceLevel.values())));
+
+        container.add(new AjaxDropDownChoicePanel<>(
+                "updateTraceLevel",
+                new ResourceModel("updateTraceLevel", "updateTraceLevel").getObject(),
+                new PropertyModel<TraceLevel>(resourceTO, "updateTraceLevel"),
+                false).
+                setChoices(Arrays.asList(TraceLevel.values())));
+
+        container.add(new AjaxDropDownChoicePanel<>(
+                "deleteTraceLevel",
+                new ResourceModel("deleteTraceLevel", "deleteTraceLevel").getObject(),
+                new PropertyModel<TraceLevel>(resourceTO, "deleteTraceLevel"),
+                false).
+                setChoices(Arrays.asList(TraceLevel.values())));
+
+        container.add(new AjaxDropDownChoicePanel<>(
+                "pullTraceLevel",
+                new ResourceModel("pullTraceLevel", "pullTraceLevel").getObject(),
+                new PropertyModel<TraceLevel>(resourceTO, "pullTraceLevel"),
+                false).
+                setChoices(Arrays.asList(TraceLevel.values())));
+
+        container.add(new AjaxTextFieldPanel(
+                "connector",
+                new ResourceModel("connector", "connector").getObject(),
+                new Model<>(resourceTO.getConnectorDisplayName()),
+                false).addRequiredLabel().setEnabled(false));
+    }
+}